linux 删除文件中匹配一个字符串但不匹配另一个字符串的行- SED、BASH?

x33g5p2x  于 2023-08-03  发布在  Linux
关注(0)|答案(4)|浏览(110)

我想删除文件中包含单词“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

字符串
正如你所看到的,我是一个新手:(

o0lyfsai

o0lyfsai1#

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

字符串
第一个模式匹配包含'test'的行;第二种模式删除行,除非它们匹配“test @”。
在数据文件上测试:

aaaa
bbbtestbbb
ccctest@ccc
test!
dddd


输出量:

aaaa
ccctest@ccc
dddd


这似乎符合你的要求。
你介意解释一下sed是如何构造和使用这个正则表达式的吗?
sed脚本的那一行中有两个正则表达式:

  1. /test/-查找包含test的行。
  2. /test@/-查找包含test@的行。
    /test/{…}表示法的意思是“当行匹配test时,在中执行该操作。
    /test@/!d的意思是“当行不匹配test@时,删除它”。
    macOS上的sed需要分号(可能还有其他基于BSD的Unix版本);它可以在GNU sed中省略,但由于它可以在两种情况下工作(我经常在macOS上测试),因此保留它似乎是明智的。它标志着!d命令的结束。
6jygbczu

6jygbczu2#

使用grep

grep -v 'test[^@]' infile

字符串
通常grep打印匹配的行,但-v告诉它打印不匹配的行。
正则表达式匹配任何出现的“test”,它后面跟着除了“@”之外的任何东西。如果您不需要在一行的末尾出现“test”,这是很好的。如果是这种情况,请使用

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


我认为不值得去探究为什么你的解决方案不起作用,因为它在很多方面都是坏的。

tcbh2hod

tcbh2hod3#

如果你把你的问题转过来一点,它就变成了:
如何从包含字符串'test@'或不包含字符串'test'的文件中筛选出所有行。
例如,可以在awk中这样做:

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

字符串
乔纳森的回答也是,我只是想给予你一个替代版本。

5fjcxozz

5fjcxozz4#

如果使用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

字符串

相关问题