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

mar*_*009 16 grep regular-expression

我有这个正则表达式:

(?<=prefix).*$
Run Code Online (Sandbox Code Playgroud)

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

grep '(?<=prefix).*$' <<< prefixSTRING
Run Code Online (Sandbox Code Playgroud)

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

Ini*_*ian 42

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

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

grep -oP '(?<=prefix).*$' <<< prefixSTRING
Run Code Online (Sandbox Code Playgroud)

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

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING
Run Code Online (Sandbox Code Playgroud)

在这个精彩的Giles 答案和实现它们的工具中详细解释了各种正则表达式风格


Kus*_*nda 38

正则表达式有许多不同的风格。您所展示的是一个类似 Perl 的正则表达式(PCRE,“Perl Compatible Regular Expression”)。

grep做 POSIX 正则表达式。这些是基本正则表达式(BRE) 和扩展正则表达式(ERE,如果grep-E选项一起使用)。请参阅手册re_formatregex您的grep手册在您的系统上引用的任何类似手册,或我刚刚链接到的 POSIX 标准文本。

如果您使用 GNU grepgrep并且与 GNUgrep特定-P选项一起使用,您将能够使用类似 Perl 的正则表达式。

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

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

如果您没有使用 GNU grep,那么您可以sed改为使用来获取字符串prefix和行尾之间的位:

sed -n 's/.*prefix\(.*\)/\1/p' file
Run Code Online (Sandbox Code Playgroud)

这样做是只打印sed设法应用给定替换的行。替换将替换与表达式匹配的整行(这是一个 BRE),用它出现在字符串之后的部分prefix

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

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


qua*_*tum 6

正如其他答案所述,grep不使用带有lookbehinds的正则表达式(默认情况下使用 GNU grep,或者根本不使用其他版本)。

如果您发现自己无法使用 GNUgreppcregrep,则可以使用(perl如果有)。

等效于的命令行perl是:

perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING
Run Code Online (Sandbox Code Playgroud)

您将所需的正则表达式放在斜杠之间。当您使用 Perl 时,它使用Perl 的正则表达式风味