正确的正则表达式在grep中不起作用


13

我有这个正则表达式:

(?<=prefix).*$

它返回字符串“ prefix”之后的任何字符,并且在任何在线正则表达式引擎(例如https://regex101.com)上都能正常工作。问题是当我在bash中使用该正则表达式时:

grep '(?<=prefix).*$' <<< prefixSTRING

它不匹配任何东西。为什么该正则表达式不适用于grep?


11
这确实凸显了regex101为什么需要JSIX,Perl / PHP和Python所需的POSIX风格选择器。我无法数出自己想要的次数。
贾里德·史密斯


而且,.*$匹配任何字符串直到行尾(或字符串结尾),而不仅仅是任何一个字符。
ilkkachu

Answers:


38

您似乎已经定义了正确的正则表达式,但是没有在命令行中设置足够的标志grep来理解它。因为默认情况下grep支持BRE并带有-E标志,所以它支持ERE。您所拥有的(先行)仅在PCRE regex风格中可用,仅在grep带有其-P标志的GNU中受支持。

假设您需要在添加一个额外的标志后提取匹配的字符串,以便知道将匹配的部分打印为prefix-ogrep

grep -oP '(?<=prefix).*$' <<< prefixSTRING

grep默认情况下,还有一个版本支持PCRE库- pcregrep您可以在其中执行

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING

美妙的Giles答案和实现每种正则表达式的工具均详细解释了各种正则表达式


38

正则表达式有许多不同的风格。您显示的是类似Perl的正则表达式(PCRE,“ Perl兼容的正则表达式”)。

grep执行POSIX正则表达式。它们是基本正则表达式(BRE)和扩展正则表达式(ERE,如果grep与该 -E选项一起使用)。请参阅系统上的手册re_formatregex类似手册grep,或我刚刚链接到的POSIX标准文本。

如果使用GNU grep,并且grepgrep特定于GNU的-P选项一起使用,则可以使用类似Perl的正则表达式。

还要注意,默认情况下grep返回,而不是行的子字符串。同样,对于GNU grep(和其他一些grep实现),您可以使用该-o选项从每行中仅获取与给定表达式匹配的位。

请注意,-P和和-o都是POSIX规范的grep非标准扩展。

如果您不使用GNU grep,则可以改用sed获取字符串prefix和行尾之间的位:

sed -n 's/.*prefix\(.*\)/\1/p' file

这样做是仅打印sed设法将给定替换应用于的行。替换将替换与表达式(即BRE)匹配的整行,并替换为出现在string之后的那一部分prefix

请注意,如果prefix一行上有多个实例,则sed变体将在最后一个实例之后返回字符串,而GNU grep变体将在一个实例之后返回字符串(其中包括的其他实例prefix)。

sed解决方案可以移植到所有类Unix系统中。


6

正如其他答案所指出的,grep不要在lookbehinds中使用正则表达式风格(默认情况下,GNU grep或其他版本完全不使用)。

如果发现自己无法使用GNU greppcregrep,则可以使用perl

与之等效的命令行为perl

perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING

您将所需的正则表达式放在斜线之间。当您使用Perl时,这将使用Perl的regex风格


或者print "$&\n" if ...如果他们只想输出prefix
ilkkachu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.