不需要整条线,只是正则expression式的匹配

我只需要从正则expression式中获得匹配:

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

输出只能是括号内的匹配项。

不要以为我可以使用grep因为它匹配整条线。

请让我知道如何做到这一点。

2件事:

  • 如@Rory所述,您需要-o选项,因此只打印匹配(而不是整行)
  • 另外,你可以使用-P选项来使用Perl正则expression式,这些expression式包括诸如Look ahead (?= )Look behind (?<= )等有用的元素,那些查找部分的东西,但实际上并不匹配和打印它们。

如果你只想要parensis内的部分匹配:

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

如果文件包含sting /(a)5667/ ,grep会打印“a”,因为:

  • /(通过\/\(find),但是因为它们处于后退 (?<= )所以不会报告它们
  • a\w匹配并因此被打印(因为-o
  • )5667/被发现b < \).+\/ ,但是因为他们在一个先行 (?= )他们没有报告

grep使用-o选项。

例如:

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

如果只需要括号中的内容,则需要支持捕获子匹配的内容(命名或编号的捕获组)。 我不认为grep或egrep可以做到这一点,perl和sed可以。 例如,用perl:

如果一个名为foo的文件中有一行,如下所示:

 /adsdds / 

你也是:

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

字母a被返回。 这可能不是你想要的。 如果你告诉我们你想要匹配什么,你可能会得到更好的帮助。 $ 1是在第一组括号中被捕获的。 2美元将是第二套等

因为除了shell之外,你还把问题标记为bash ,除grep之外还有另一个解决scheme:

Bash自3.0版本开始就有自己的正则expression式引擎,像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将整个string作为整个正则expression式的匹配,所以<Lane>8</Lane>
  • ${BASH_REMATCH[1]}将给出与第一组匹配的部分,因此只有8
  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 

这将完成你的要求,但我不认为这是你真正想要的。 我把正则expression式前面的.*放在比赛前吃东西,但这是一个贪婪的操作,所以它只能匹配string中的倒数第二个\w字符。

请注意,你需要逃避parens和+

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

假设该文件包含:

 $ 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

所有将打印一个string“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