' grep -w -f"的行为当有多个/不完整的匹配

时间:2014-05-06 22:56:02

标签: regex macos bash grep

我正在使用grep -w -f从与模式匹配的文件中提取行。但是,如果输入模式文件中的模式与模式不完全匹配,则它似乎屏蔽了稍后在输入模式文件中出现的完整匹配。我还缺少另一个grep选项吗?例如:

$ head list
tt140
tt1351
tt1354
tt998
tt1122

$ head match1
tt135
tt1122
tt1351

$ grep -w -f match1 list
tt1122

tt135中的第一个模式match1似乎会干扰后来的tt1351。如果删除第一行,则会报告tt1351匹配。

$ head match2
tt1122
tt1351

$ grep -w -f match2 list
tt1351
tt1122

这是预期的行为吗?是否有另一种选择传递给grep以避免这种情况?

2 个答案:

答案 0 :(得分:3)

事实上,正如@japyal所述, BSD 版本grep 中似乎存在错误(这也会影响OSX)。

解决方法

 grep -f <(sed 's/.*/\\<&\\>/' match1) list

这会动态地将match1中的字符串包含在显式字边界正则表达式断言中,就像match1被定义为:

\<tt135\>
\<tt1122\>
\<tt1351\>

净效果与指定-w的效果相同。

答案 1 :(得分:0)

如果你不能按照mklement0的建议修改match1,你可以使用shell cmds创建-w -f功能来构造一个等效的grep cmd:

> egrep `cat match1 | xargs -d '\n' | sed 's/^/(\\</; s/$/\\>)/; s/ /\\>|\\</g;'` list
tt1351
tt1122

我没有Mac或BSD来验证,但这适用于我。

说明:反引号中的部分正在构造所需的正则表达式,然后在香草egrep cmd中使用。

> cat match1 | xargs -d '\n' | sed 's/^/(\\</; s/$/\\>)/; s/ /\\>|\\</g;'
(\<tt135\>|\<tt1122\>|\<tt1351\>)