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

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

我有这个正则表达式:

(?<=prefix).*$

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

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

它不匹配任何东西。为什么正则表达式不能与 grep 一起使用?

答案1

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

假设你需要提取仅有的匹配字符串后prefix需要添加一个额外的标志-o来让grepprint知道仅有的匹配部分为

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

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

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

关于各种正则表达式风格的详细解释在这篇精彩的文章中进行了解释贾尔斯的回答以及实现它们的工具

答案2

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

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

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

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

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

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

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

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

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

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

答案3

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

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

与 等效的命令perl行是:

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

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

相关内容