Я хочу обработать тело текста и извлечь целое число из определенного положения в тексте, но я не уверен, как описать то 'особое положение'. Регулярные выражения действительно смущают меня. Я потратил (потратил впустую) пару часов, читая учебные руководства, и я чувствую себя не ближе к ответу :(
Существует набор текста, который может или не может включать целые числа (что я не хочу) и затем существует строка, которая всегда содержит
id_ad=1929170&action
и затем сопровождаемый набором мусора я не забочусь о, снова он может или не может включать одно или несколько целых чисел.
Так интуитивно я знаю, что просто хочу проигнорировать все до (и включая) id_ad=
и проигнорируйте все после (и включая) &action
и меня оставят с целым числом, которое я хочу. И я знаю, что могу использовать регулярные выражения для достижения этого. Но я, может казаться, не понимаю это.
Я хотел бы сделать это как один лайнер от терминала, если это возможно.
Не так один лайнер (хотя команда для выполнения его является одним лайнером :)), но вот опция Python:
#!/usr/bin/env python3
import sys
file = sys.argv[1]
with open(file) as src:
text = src.read()
starters = [(i+6, text[i:].find("&action")+i) for i in range(len(text)) if text[i:i+6] == "id_ad="]
if len (starters) > 0:
for item in starters:
print(text[item[0]:item[1]])
Сценарий сначала перечисляет все случаи (индексы) (запуск) строка "id_ad = ", в сочетании с (концом) строка" &action". Затем это печатает все, что является между теми "маркерами".
Извлеченный из подготовленного файла:
"Я хочу обработать тело текста и извлечь целое число из определенного положения в тексте, но я не уверен, как описать то 'особое положение'. Регулярные выражения действительно смущают меня. Я потратил (потратил впустую) пару часов, читая учебные руководства, и я чувствую себя не ближе к ответу :( Существует набор текста, который может или не может включать целые числа (что я не хочу) и затем существует строка, которая всегда содержит id_ad=1929170&action существует набор текста, который может или не может включать целые числа (что я не хочу) и затем существует строка, которая всегда содержит id_ad=1889170&action и затем сопровождаемый набором мусора, о котором я не забочусь, снова это может или не может включать одно или несколько целых чисел. Существует набор текста, который может или не может включать целые числа (что я не хочу) и затем существует строка, которая всегда содержит id_ad=1889170&action и затем сопровождаемый набором мусора, о котором я не забочусь, снова это может или не может включать одно или несколько целых чисел. Существует набор текста, который может или не может включать целые числа (что я не хочу) и затем существует строка, которая всегда содержит id_ad=1929990&action"
Результат:
1929170
1889170
1889170
1929990
Вставьте сценарий в пустой файл, сохраните его как extract.py
выполните его командой:
python3 <script> <file>
Если существует только одно возникновение в текстовом файле, сценарий может быть намного короче:
#!/usr/bin/env python3
import sys
file = sys.argv[1]
with open(file) as src:
text = src.read()
print(text[text.find("id_ad=")+6:text.find("&action")])
Например:
egrep "id_ad=[[:digit:]]+&action" file.txt | tr "=&" " " | cut -d " " -f2
..., но я уверен, что существуют более изящные пути;-).
Шаг за шагом:
egrep "id_ad=[[:digit:]]+&action" file.txt
сканирование file.txt
для шаблона (регулярное выражение), которое составлено литералом id_ad=
, сопровождаемый 1 или более цифрами (значение [[:digit:]]+
, сопровождаемый литералом &action
. Отправьте вывод в стандартный вывод.
tr "=&" " "
преобразовывает символы "=" и "&"; в два пробелов.
cut -d " " -f2
печатают второе поле (разделенное пробелом) из стандартного входа.
sed 's/id_ad=\(.*\)&action/\1/' filename
Приведенная выше команда возвращает любые строки (.*
) между двумя словами START (id_ad=
) и словом END (&action
) в имени файла.
\(...\)
Используется для захвата групп. \(
является началом группы захвата и заканчивается \)
. А с помощью \1
мы печатаем его групповой индекс (у нас есть одна группа захвата)
Лучшая команда sed
для вышеуказанного решения может быть такой:
sed 's/^id_ad=\([0-9]*\)&action/\1/' filename
^
Start линии.
[0-9]*
: любое число с 0 или более экземплярами.
Подробнее о команде sed см. В
grep -Po '(?<=id_ad=)[0-9]*(?=&action)' filename
От man grep:
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
-P, --perl-regexp
Interpret PATTERN as a Perl compatible regular expression (PCRE)
Возвращает любое число с 0 или более вхождениями ([0-9]*
) между двумя словами START (id_ad=
) и END (&action
) в имени файла.
(?<=pattern)
: позитивный взгляд назад. Пара круглых скобок, с открывающей скобкой, за которой следует знак вопроса, символ «меньше чем» и знак равенства.
(?<=id_ad=)[0-9]*
(положительный вид сзади) соответствует 0 или более появлений чисел, которые следуют после id_ad=
в имени файла.
(?=pattern)
: положительный прогноз: конструкция «положительный взгляд» представляет собой пару круглых скобок, с открывающей скобкой, за которой следует знак вопроса и знак равенства.
[0-9]*(?=&action)
: (положительный прогноз) сопоставляет 0 или более вхождений чисел, за которыми следует шаблон (&action
), не делая шаблон (&action
) частью соответствия.
Подробнее о Lookahead и Lookbehind
Дополнительные ссылки:
Расширенные темы Grep ]
GREP для дизайнеров
Другой ответ Python через re
модуль. Пример украден от сообщения Jacob.
script.py
#!/usr/bin/python3
import sys
import re
file = sys.argv[1]
L = [] # Declare an empty list
with open(file) as src:
for j in src: # iterate through all the lines
for i in re.findall(r'id_ad=(\d+)&action', j): # extracts the digits which was present in-between `id_ad=` and `&action` strings.
L.append(i) # Append the extracted digits to the already declared empty list L.
for f in L: # Iterate through all the elements in the list L
print(f) # Print each element from the list L in a separate new line.
Запустите вышеупомянутый скрипт как,
python3 script.py /path/to/the/file
Пример:
$ cat fi
I want to process the body of text and extract an integer from a specific position in the text, but I'm not sure how to describe that 'particular position'. Regular expressions really confuse me. I spent (wasted) a couple hours reading tutorials and I feel no closer to an answer :( There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains
id_ad=1929170&action There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains id_ad=1889170&action and then followed by a bunch of garbage I don't care about, again it may or may not include one or more integers. There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains
id_ad=1889170&action and then followed by a bunch of garbage I don't care about, again it may or may not include one or more integers. There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains id_ad=1929990&action
$ python3 script.py ~/file
1929170
1889170
1889170
1929990