Назад | Перейти на главную страницу

Не нужна вся строка, только совпадение из регулярного выражения

Мне просто нужно найти совпадение из регулярного выражения:

$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"

На выходе должно быть только то, что было найдено в круглых скобках.

Не думаю, что я могу использовать grep потому что он соответствует всей строке.

Пожалуйста, дайте мне знать, как это сделать.

Использовать -o вариант в grep.

Например:

$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar

2 вещи:

  • Как заявил @Rory, вам нужен -o вариант, поэтому печатается только совпадение (вместо всей строки)
  • Кроме того, вам нужен -P вариант, чтобы использовать регулярные выражения Perl, которые включают полезные элементы, такие как Смотреть вперед (?= ) и Смотреть за (?<= ), они ищут детали, но не сопоставляют их и не распечатывают.

Если вы хотите, чтобы совпадала только часть внутри парнезиса:

grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt

если файл содержит жало /(a)5667/, grep напечатает 'a', потому что:

  • /( найдены \/\(, но поскольку они находятся в смотреть за (?<= ) они не сообщаются
  • a соответствует \w и таким образом печатается (из-за -o )
  • )5667/ находятся b < \).+\/, но поскольку они находятся в смотреть вперед (?= ) они не сообщаются
    sed -n "s/^.*\(captureThis\).*$/\1/p"

-n      don't print lines
s       substitute
^.*     matches anything before the captureThis 
\( \)   capture everything between and assign it to \1 
.*$     matches anything after the captureThis 
\1      replace everything with captureThis 
p       print it

Если вам нужно только то, что указано в круглых скобках, вам нужно что-то, что поддерживает захват под совпадений (именованные или нумерованные группы захвата). Я не думаю, что grep или egrep могут это сделать, perl и sed могут. Например, с perl:

Если файл с именем foo содержит следующую строку:

/adsdds      /

А вы делаете:

perl -nle 'print $1 if /\/(\w).+\//' foo

Буква а возвращается. Хотя это может быть не то, что вам нужно. Если вы сообщите нам, что вы пытаетесь сопоставить, возможно, вам помогут лучше. $ 1 - это то, что было заключено в первые скобки. 2 доллара будет вторым комплектом и т. Д.

Потому что вы отметили свой вопрос как трепать в дополнении к оболочка, кроме grep :

Начиная с версии 3.0 Bash имеет собственный механизм регулярных выражений, использующий =~ оператор, как и Perl.

теперь, учитывая следующий код:

#!/bin/bash
DATA="test <Lane>8</Lane>"

if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
        echo $BASH_REMATCH
        echo ${BASH_REMATCH[1]}
fi
  • Обратите внимание, что вы должны вызывать его как bashи не только sh чтобы получить все расширения
  • $BASH_REMATCH предоставит всю строку, совпадающую со всем регулярным выражением, поэтому <Lane>8</Lane>
  • ${BASH_REMATCH[1]} даст деталь, совпадающую с 1-й группой, поэтому только 8

Предполагая, что файл содержит:

$ cat file
Text-here>xyz</more text

И вам нужен персонаж (и) между > и </ , вы можете использовать:

grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed -nE 's:^.*>(\w+)</.*$:\1:p' file
awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
perl -nle 'print $1 if />(\w+)<\//' file

Все напечатают строку «xyz».

Если вы хотите записать цифры этой строки:

$ cat file
Text-<here>1234</text>-ends

grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed -E 's:^.*>([0-9]+)</.*$:\1:' file
awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
perl -nle 'print $1 if />([0-9]+)<\//' file

Это выполнит то, что вы просите, но я не думаю, что вы действительно этого хотите. Я положил .* перед регулярным выражением, чтобы съесть что-либо перед матчем, но это жадная операция, поэтому она соответствует только предпоследнему \w символ в строке.

Обратите внимание, что вам нужно избегать паренсов и +.

sed 's/.*\(\w\).\+/\1/' myfile.txt