Я вижу множество примеров и справочных страниц о том, как выполнять такие вещи, как поиск и замена с помощью sed, awk или gawk.
Но в моем случае у меня есть регулярное выражение, которое я хочу применить к текстовому файлу для извлечения определенного значения. Я не хочу выполнять поиск и замену. Это вызывается из bash. Возьмем пример:
Пример регулярного выражения:
.*abc([0-9]+)xyz.*
Пример входного файла:
a
b
c
abc12345xyz
a
b
c
Как бы просто это ни звучало, я не могу понять, как правильно вызвать sed / awk / gawk. То, что я надеялся сделать, находится в моем сценарии bash:
myvalue=$( sed <...something...> input.txt )
Вот что я пробовал:
sed -e 's/.*([0-9]).*/\\1/g' example.txt # extracts the entire input file
sed -n 's/.*([0-9]).*/\\1/g' example.txt # extracts nothing
Ответы:
Моя
sed
(Mac OS X) не работала с+
. Я попробовал*
вместо этого и добавилp
тег для печати совпадения:Для сопоставления хотя бы одного числового символа без
+
, я бы использовал:источник
+
и тогда это сработало для меня:sed -n 's/^.*abc\([0-9]\+\)xyz.*$/\1/p'
Вы можете использовать sed для этого
-n
не печатайте получившуюся строку-r
это делает так, чтобы у вас не было выхода из парсеров группы захвата()
.\1
совпадение группы захвата/g
глобальный матч/p
распечатать результатЯ написал для себя инструмент, который упрощает эту задачу
источник
Я использую,
perl
чтобы облегчить себе задачу. напримерЭто запускает Perl,
-n
опция указывает Perl читать по одной строке из STDIN и выполнять код. Параметр-e
указывает инструкцию для выполнения.Инструкция запускает регулярное выражение в прочитанной строке, и, если оно совпадает, распечатывает содержимое первого набора скобок (
$1
).Вы также можете сделать это с несколькими именами файлов в конце. например
perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/' example1.txt example2.txt
источник
Если ваша версия
grep
поддерживает это, вы можете использовать-o
опцию для печати только той части любой строки, которая соответствует вашему регулярному выражению.Если нет, то вот лучшее, что
sed
я мог придумать:... который удаляет / пропускает без цифр, а для оставшихся строк удаляет все начальные и конечные нецифровые символы. (Я только предполагаю, что вы собираетесь извлечь число из каждой строки, содержащей его).
Проблема с чем-то вроде:
.... или
...
sed
поддерживает только "жадное" совпадение ... поэтому первый. * будет соответствовать остальной части строки. Если мы не можем использовать инвертированный символьный класс для достижения нежадного совпадения ... или версиюsed
с Perl-совместимыми или другими расширениями его регулярных выражений, мы не сможем извлечь точное совпадение с шаблоном из пространства шаблонов (строка ).источник
sed
команды следующим образом:sed -n 's/[^0-9]*\([0-9]\+\).*/\1/p'
grep -o
! Я пытался сделать этоsed
и боролся с моей необходимостью найти несколько совпадений в некоторых строках. Мое решение - stackoverflow.com/a/58308239/117471Вы можете использовать
awk
withmatch()
для доступа к захваченной группе:Это пытается соответствовать шаблону
abc[0-9]+xyz
. В этом случае он сохраняет свои срезы в массивеmatches
, первым элементом которого является блок[0-9]+
. Посколькуmatch()
возвращает позицию символа или индекс начала этой подстроки (1, если она начинается в начале строки) , он запускаетprint
действие.С
grep
вы можете использовать просмотровую позади и смотреть вперед:Это проверяет шаблон ,
[0-9]+
когда это происходит внутриabc
иxyz
и просто печатает цифры.источник
perl - самый чистый синтаксис, но если у вас нет perl (не всегда, насколько я понимаю), то единственный способ использовать gawk и компоненты регулярного выражения - использовать функцию gensub.
вывод образца входного файла будет
Примечание: gensub заменяет все регулярное выражение (между //), поэтому вам нужно поставить. * До и после ([0-9] +), чтобы избавиться от текста до и после числа в подстановке.
источник
match()
для доступа к захваченным группам. См. Мой ответ по этому поводу .Если вы хотите выделить строки, удалите ненужные биты:
Он в основном выбирает нужные строки,
egrep
а затем используетsed
для удаления битов до и после числа.Вы можете увидеть это в действии здесь:
Обновление: очевидно, если ваша реальная ситуация более сложна, мне нужно будет изменить RE. Например, если у вас всегда было одно число, заключенное в ноль или более нечисловых чисел в начале и в конце:
источник
Случай OP не указывает, что в одной строке может быть несколько совпадений, но для трафика Google я также добавлю пример для этого.
Поскольку OP необходимо извлечь группу из шаблона, для использования
grep -o
потребуется 2 прохода. Но я все еще считаю это наиболее интуитивным способом выполнения работы.Поскольку процессорное время в основном бесплатное, но удобочитаемость бесценна, я стараюсь рефакторировать свой код, исходя из вопроса: «Что я буду думать через год?» Фактически, для кода, которым я собираюсь поделиться публично или с моей командой, я даже открою,
man grep
чтобы выяснить, какие есть длинные варианты, и заменить их. Вот так:grep --only-matching --extended-regexp
источник
ты можешь сделать это с оболочкой
источник
Для awk. Я бы использовал следующий сценарий:
источник
([0-9+])
, это выводит всю строку.источник