删除文件中匹配一个string但不匹配另一个string的行 – SED,BASH?

我想删除包含单词“test”的文件中的所有行,但如果该行包含“test @”,那么我不想删除它。

有可能是一些这样做与sed的时髦的方式,但我挣扎,我试图用sed写一个bash循环,但这可能是愚蠢的。

filetest=/tmp/filetest filetest_tmp=/tmp/filetest.tmp< line_num=0 while read line; do line_num=$(($line_num+1)) if [[ $line == *rootsh* ]] && [[ $line != *root@* ]] then sed -e "${line_num}"'d' $filetest >> $filetest_tmp fi done < $filetest cp $syslog_tmp $filetest 

你可以告诉我,我是一个newb在这:(

 sed -e '/test/{/test@/!d;}' 

第一种模式与包含“测试”的行匹配; 第二个模式删除行,除非它们匹配“test @”。

测试数据文件:

 aaaa bbbtestbbb ccctest@ccc test! dddd 

输出:

 aaaa ccctest@ccc dddd 

这似乎符合你的要求。

使用grep

 grep -v 'test[^@]' infile 

通常grep打印匹配的行,但-v告诉它打印不匹配的行。

正则表达式匹配任何“test”后面跟着“@”的任何内容。 如果你不必期望在测试结束时出现“测试”,这很好。 如果是这种情况,请使用

 grep -E -v 'test([^@]|$)' 

我不认为这是值得去解释为什么你的解决方案不起作用,因为它在很多方面被打破。

如果你稍微翻一下你的问题,它会变成:

如何过滤掉包含字符串“test @”或不包含字符串“test”的文件中的所有行。

这可以例如在awk中完成,像这样:

 awk '!/foo/ || /foo@/' testfile 

乔纳森的答案也有效,我只是想给你一个替代版本。

如果使用ed则不需要tmp文件!

 # cf. http://wiki.bash-hackers.org/howto/edit-ed cat <<-'EOF' | ed -s file H ,g/test$/d ,g/test[^@]/d wq EOF