我有这个正则表达式:
(?<=prefix).*$
它返回字符串“前缀”之后的任何字符,并且它在任何在线正则表达式引擎上都可以正常工作(例如https://regex101.com)。问题是当我在 bash 中使用该正则表达式时:
grep '(?<=prefix).*$' <<< prefixSTRING
它不匹配任何东西。为什么正则表达式不能与 grep 一起使用?
答案1
您似乎已经定义了正确的正则表达式,但没有在命令行中设置足够的标志来grep
理解它。因为默认情况下grep
支持 BRE,并且使用-E
标志它支持 ERE。您所拥有的(前瞻)仅在 PCRE 正则表达式风格中可用,该风格仅在grep
带有其-P
标志的 GNU 中受支持。
假设你需要提取仅有的匹配字符串后prefix
需要添加一个额外的标志-o
来让grep
print知道仅有的匹配部分为
grep -oP '(?<=prefix).*$' <<< prefixSTRING
还有一个grep
默认支持 PCRE 库的版本 -pcregrep
你可以在其中做
pcregrep -o '(?<=prefix).*$' <<< prefixSTRING
关于各种正则表达式风格的详细解释在这篇精彩的文章中进行了解释贾尔斯的回答以及实现它们的工具
答案2
正则表达式有许多不同的风格。您所展示的是一个类似 Perl 的正则表达式(PCRE,“Perl 兼容正则表达式”)。
grep
执行 POSIX 正则表达式。这些都是基本正则表达式(布雷)和扩展正则表达式(ERE,ifgrep
与选项一起使用 -E
)。请参阅手册re_format
或regex
您的手册在您的系统上引用的任何类似手册grep
,或者我刚刚链接到的 POSIX 标准文本。
如果您使用 GNU ,并且与 GNU特定选项一起grep
使用,您将能够使用类似 Perl 的正则表达式。grep
grep
-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
,或者根本不使用其他版本)。
如果您发现自己无法使用 GNUgrep
或pcregrep
,则可以使用(perl
如果有的话)。
与 等效的命令perl
行是:
perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING
您将所需的正则表达式放在斜杠之间。当您使用 Perl 时,这会使用Perl 的正则表达式风格。