如何在sed的正则表达式中使用[\ w] +?


24

我在Windows上,但我想我的问题仍然正确地放在这里。

C:\Users\User>grep --version
GNU grep 2.6.3

C:\Users\User>sed --version
GNU sed version 4.2.1

我注意到以下工作原理(输出here):

echo here | grep -E "\w+"
echo here | grep -E "[her]+"

但是,这不起作用(不输出任何内容):

echo here | grep -E "[\w]+"

再次这样做(输出here):

echo here | grep -P "[\w]+"

我想这[\w]是Perl正则表达式特有的。那是对的吗?

所以,让我们谈谈sed。这有效(输出gone):

echo here | sed -r "s/\w+/gone/"
echo here | sed -r "s/[her]+/gone/"

再次,这不(输出here):

echo here | sed -r "s/[\w]+/gone/"

现在,我如何激活sed的Perl正则表达式-有什么办法吗?

Answers:


11

不同的工具及其版本支持正则表达式的不同变体。每个文档都会告诉您他们支持什么。

存在标准,以便人们可以依赖所有符合标准的应用程序可用的最少功能集。

例如,POSIX(至少一个版本或该标准的另一个版本,但该标准在过去的几十年中在此方面没有太大发展)的所有现代实现sedgrep实现都由POSIX指定。

在POSIX BRE和ERE中,您拥有[:alnum:]角色类。这与您的语言环境中的字母和数字相匹配(请注意,a-zA-Z0-9除非语言环境为C,否则通常包含的内容要多得多)。

所以:

grep -x '[[:alnum:]_]\{1,\}'

匹配一个或多个数字或_。

[\w]POSIX要求它匹配反斜杠或w。因此,您将找不到可用的grepsed实现(除非通过非标准选项)。

\wPOSIX并未指定单独的行为,因此允许实现执行其所需的操作。GNU grep在很久以前就添加了。

GNU grep曾经拥有自己的regexp引擎,但是现在它使用GNU libc的regexp引擎(尽管它确实嵌入了自己的副本)。

这是为了在您的语言环境中匹配数字和下划线。但是,它当前存在一个错误,即仅匹配单字节字符(例如,在UTF-8语言环境中不匹配é,即使这显然是一个字母,并且即使在é是单个字符的所有语言环境中都匹配é字符)。

\w在perl regexp和PCRE中也有一个regexp运算符。PCRE / perl不是POSIX正则表达式,它们完全是另一回事。

现在,通过GNU grep -P使用PCRE 的方式,它遇到了和不使用相同的问题-P。尽管可以使用(*UCP)(但在非UTF8语言环境中也有副作用),但可以在此附近进行工作。

GNU sed还将GNU libc的正则表达式用于其自己的正则表达式。它以某种方式使用它,尽管它没有与GNU相同的错误grep

GNU sed不支持PCRE。在代码中有一些证据表明它曾经尝试过,但是似乎不再在议程上了。

如果您想要Perl的正则表达式,则只需使用perl

否则,我要说的是,与其尝试依靠sed/ 的特定实现的虚假的非标准功能,grep不如坚持使用标准和use [_[:alnum:]]


[_[:alnum:]]是一个很好的解决办法,让我把它扩大,就像[\w/][_[:alnum:]/]在这种情况下)。
贝尔

1
关于GNU的局限性,现在这个答案已经过时了grep
斯特凡Chazelas

7

您是正确的- \w是PCRE的一部分-perl兼容的正则表达式。但是,它不是“标准”正则表达式的一部分。http://www.regular-expressions.info/posix.html

某些版本的软件sed可能支持它,但我建议最简单的方法是通过指定标志perlsed模式下使用-p。(与一起-e)。(中的更多详细信息perlrun

但是[]在该示例中,您不需要它-这是针对有效材料组的。

echo here  | perl -pe 's/\w+/gone/'

或在Windows上:

C:\>echo here  | perl -pe "s/\w+/gone/"
gone
C:\>echo here  | perl -pe "s/[\w\/]+/gone/"
gone

查看perlre更多PCRE内容。

您可以在这里获得perl:http : //www.activestate.com/activeperl/downloads


请注意\w[\w]在我的问题之间的区别。我将使用每个命令的输出来更新它,以弄清哪个正在工作,哪个不工作。尤其sed了解\w,但不了解[\w]。另外,我需要[\w]工作,因为我想使用[\w/]例如。
BER的

在这种情况下,这可能是一个报价问题。无论哪种方式- perl都可以做到:)。
2015年

谢谢!StéphaneChazelas的回答离我的要求有点接近(因为我没有安装perl,我猜是du * b Windows用户),所以我接受了他的回答。
贝尔

可以-但是我建议在Windows上安装Perl。这是我的第一件事,我发现它非常有用。
2015年

\w在perl和GNU emacs中甚至在此之前就已经在GNU grep(80年代)中使用了。
斯特凡Chazelas

1

我怀疑grep并且sed正在决定何时应用[]以及何时扩展\w。在perl中,正则表达式\w表示任何单词字符,并[]定义一个组以将其中的任何字符用作匹配项。如果“扩展” \w之前的[],它将是所有单词字符的字符类。如果,而是你[]首先你将会有两个字符的字符类\,并w因此将匹配包含一个或一个以上的这两个字符的任意图案。

因此,似乎sed[]将视为并将其视为包含要匹配的确切字符,而不是\w像as perlgrepdo 那样遵循特殊序列。当然,[]在此示例中完全没有必要使用,但是也许可以想象一下在其中重要的情况,但是随后您可以使其与parens和ors一起使用。


如果是这样,我会感到惊讶。\ 是一个转义代码,您可以将其用于转义定界符。从本质上讲,这意味着它必须具有比其他任何事物更高的优先级。我认为更有可能因为它不是\w正则表达式规范的一部分而未实现
Sobrique 2015年

好吧,从经验上来说,为我使用gnu sed似乎是一种情况:echo whe\\ere | sed -r 's/[\w]+/gone/g给我的感觉gonehegoneere就像是匹配每个` and w`并进行替换
Eric Renouf

我可以确认Eric Renouf看到了什么。因此,我们想以某种方式取消转义反斜杠?:)
bers 2015年

我认为这不是正确的答案。Sed不支持混合使用不同类型的字符类定义,因此答案是,如果您必须同时使用两种类型的字符类,请选择其他工具,或者如果您选择sed,请使用其支持的语法
Eric Renouf
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.