Grep 正则表达式未按预期工作

Posted

技术标签:

【中文标题】Grep 正则表达式未按预期工作【英文标题】:Grep regular expression not working as expected 【发布时间】:2022-01-02 18:27:46 【问题描述】:

我有一个简单的grep 命令试图只获取 CSV 文件的第一列,包括逗号。是这样的……

grep -Eo '^[^,]+,' some.csv

所以在我的脑海中,这读起来就像“只给我匹配的部分,每行至少以一个不是逗号的字符开头,然后是一个逗号。”

所以在文件some.csv 上,看起来像这样:

column1,column2,column3,column4
column1,column2,column3,column4
column1,column2,column3,column4

我期待这个输出:

column1,
column1,
column1,

但是我得到了这个输出:

column1,
column2,
column3,
column1,
column2,
column3,
column1,
column2,
column3,

这是为什么呢? 我的 grep/regex 缺少什么?我的预期输出不正确吗?

如果我删除正则表达式中尾随逗号的要求,该命令将按预期工作。

grep -Eo '^[^,]+' some.csv

给我:

column1
column1
column1

注意:我在 macOS High Sierra 上使用 grep 版本:grep (BSD grep) 2.5.1-FreeBSD

【问题讨论】:

这不是与 GNU grep 的唯一区别。如果您看到更多这样的差异,just install GNU grep 可能比works as expected 更好。 我看到了一些与 BSD grep 中的错误有关的问题... 1) unix.stackexchange.com/questions/352977/… 2) unix.stackexchange.com/questions/398223/… 3) unix.stackexchange.com/questions/428340/… .. 解决方法可能是改用 sed/awk 包括 awk 在内的 BSD 工具有问题,最好尽量避免。获取 GNU 工具。话虽如此,即使是BSD sed 也应该能够处理sed 's/^\([^,]*,\).*/\1/' file 【参考方案1】:

BSD grep 通常是错误的。请参阅以下相关帖子:

Why does this BSD grep result differ from GNU grep? grep strange behaviour with single letter words How to make BSD grep respect start-of-line anchor

上面的最后一个链接提到了您的情况:当使用 -o 选项时,grep 出于某种原因忽略了 ^ 锚点。这个问题也在FreeBSD bug中描述:

我注意到相同版本的 grep 存在更多问题。我不 知道它们是否相关,但我现在将它们附加到这里。

$ printf abc | grep -o '^[a-c]'

应该只打印'a',而是针对每个字母给出三个命中 传入的文本。

作为一种解决方法,最好只安装GNU grep 而不是works as expected。

或者,使用带有 BRE POSIX 模式的 sed

sed -i '' 's/^\([^,]*,\).*/\1/' file

模式匹配的地方

^ - 行首 \([^,]*,\) - 第 1 组(后来用 RHS 的 \1 反向引用引用): [^,]* - 除了, 之外的零个或多个字符 , - 一个 , 字符 .* - 该行的其余部分。

请注意,-i 将就地更改文件内容。如果需要,请使用 -i.bak 创建备份文件(不过,您将不需要下一个空的 '')。

【讨论】:

Mac 没有附带 BSD grep,它带有 GNU grep 2.5 - 最后一个 GPL2 许可的 GNU grep。我无法在 FreeBSD 上重现该问题。 FreeBSD 曾经使用过 GNU grep,因此出现了 2012 年的错误报告。

以上是关于Grep 正则表达式未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

LDAP olcAccess 正则表达式未按预期工作

使用正则表达式查找命令未按预期工作

NLTK - nltk.tokenize.RegexpTokenizer - 正则表达式未按预期工作

js 正则表达式未按预期工作。未检测到换行符[重复]

C++ 11 正则表达式未按预期返回组

正则表达式未按预期进行评估