我有一个简单的grep命令尝试仅获取 CSV 文件的第一列(包括逗号)。事情是这样的……
grep -Eo '^[^,]+,' some.csv
Run Code Online (Sandbox Code Playgroud)
所以在我的脑海中,这读起来就像“只给我该行的匹配部分,其中每行至少以一个不是逗号的字符开头,后跟一个逗号。”
所以在文件 上,some.csv看起来像这样:
column1,column2,column3,column4
column1,column2,column3,column4
column1,column2,column3,column4
Run Code Online (Sandbox Code Playgroud)
我期待这个输出:
column1,
column1,
column1,
Run Code Online (Sandbox Code Playgroud)
但我得到这个输出:
column1,
column2,
column3,
column1,
column2,
column3,
column1,
column2,
column3,
Run Code Online (Sandbox Code Playgroud)
这是为什么?我的 grep/regex 中缺少什么?我的预期输出不正确吗?
如果我删除正则表达式中尾随逗号的要求,该命令将按我的预期工作。
grep -Eo '^[^,]+' some.csv
Run Code Online (Sandbox Code Playgroud)
给我:
column1
column1
column1
Run Code Online (Sandbox Code Playgroud)
注意:我在 macOS High Sierra 上使用 grep 版本:grep (BSD grep) 2.5.1-FreeBSD
BSDgrep总体来说是有缺陷的。请参阅以下相关帖子:
上面的最后一个链接提到了您的情况:-o使用选项时,由于某种原因grep忽略^锚点。FreeBSD bug中也描述了这个问题:
我注意到同一版本的 grep 还有一些问题。我不知道它们是否相关,但我现在将它们附加在这里。
$ printf abc | grep -o '^[a-c]'应该只打印“a”,而是针对传入文本的每个字母给出三次命中。
作为解决方法,安装按预期工作的GNU grep可能是一个更好的主意。
sed或者,与 BRE POSIX 模式一起使用:
sed -i '' 's/^\([^,]*,\).*/\1/' file
Run Code Online (Sandbox Code Playgroud)
模式匹配的地方
^- 一行的开头\([^,]*,\)- 第 1 组(稍后通过\1RHS 反向引用进行引用):
[^,]*- 零个或多个字符以外的字符,,- 一个,字符.*- 该行的其余部分。请注意,这-i将更改文件内容。如果需要,可用于-i.bak创建备份文件(这样,您就不需要下一个空文件''了)。