使用带有否定前瞻断言的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