Мне просто нужно найти совпадение из регулярного выражения:
$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"
На выходе должно быть только то, что было найдено в круглых скобках.
Не думаю, что я могу использовать grep потому что он соответствует всей строке.
Пожалуйста, дайте мне знать, как это сделать.
Использовать -o
вариант в grep
.
Например:
$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar
2 вещи:
-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 grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed sed -nE 's:^.*>(\w+)</.*$:\1:p' file
awk awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
Perl perl -nle 'print $1 if />(\w+)<\//' file
Все напечатают строку «xyz».
Если вы хотите записать цифры этой строки:
$ cat file
Text-<here>1234</text>-ends
grep grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed sed -E 's:^.*>([0-9]+)</.*$:\1:' file
awk awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
Perl perl -nle 'print $1 if />([0-9]+)<\//' file
Это выполнит то, что вы просите, но я не думаю, что вы действительно этого хотите. Я положил .*
перед регулярным выражением, чтобы съесть что-либо перед матчем, но это жадная операция, поэтому она соответствует только предпоследнему \w
символ в строке.
Обратите внимание, что вам нужно избегать паренсов и +
.
sed 's/.*\(\w\).\+/\1/' myfile.txt