使用带有否定前瞻断言的grep

我有与这篇文章完全相同的问题,但是在 bash 中,正则表达式对我不起作用。正则表达式排除,寻找一个没有跟在另一个词后面的词

我想包含包含单词“Tom”的 csv 文件的所有行,除非后面跟着“Thumb”。

  • 包括:汤姆坐在海边。
  • 不包括:Tom Thumb 坐在海边。
  • 包括:Tom 和 Tom Thumb 坐在海边。

Tom(?!s+Thumb)当我在 regex101.com 上试用时,正则表达式可以工作。

但是我已经尝试了所有这些变体,但没有一个起作用。我错过了什么,我该如何解决这个问题?我在 Mac 上。

cat inputfile.csv | grep Tom(?!s+Thumb) > Tom.csv
cat inputfile.csv | egrep Tom(?!s+Thumb) > Tom.csv
cat inputfile.csv | egrep “Tom(?!s+Thumb)” > Tom.csv
cat inputfile.csv | grep -E Tom(?!s+Thumb) > Tom.csv
cat inputfile.csv | grep -E “Tom(?!s+Thumb)” > Tom.csv

回答

你不能用 POSIX ERE 做到这一点。

POSIX 扩展正则表达式中没有否定前瞻断言,这是语法grep -E激活。

您可以获得的最接近的是组合两个单独的正则表达式,一个正匹配和一个负匹配:

grep -we 'Tom' inputfile.csv | grep -wvEe 'Tom[[:space:]]Thumb'

grep -v 排除与给定表达式匹配的任何行;所以在这里,我们首先搜索Tom,然后删除Tom Thumb

但是,匹配的意图Tom and Tom Thumb sat by the seashore使这行不通。简而言之:你不能用标准做你要求的事情grep,除非它必须grep -P使你的原始语法有效。在这种情况下,您可以使用:

grep -Pwe 'Tom(?!s+Thumb)' <inputfile.csv >Tom.csv

一次黑客攻击可能是临时替代

假设您uuidgen可以(它似乎存在于 Big Sur)来生成一个临时的、不可预测的印记:

uuid=$(uuidgen)
sed -e "s/Tom Thumb/$uuid/g" <inputfile.csv 
  | grep -we 'Tom' 
  | sed -e "s/$uuid/Tom Thumb/g" >tom.csv


以上是使用带有否定前瞻断言的grep的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>