【问题标题】:Delete line in file matching one string but not matching another - SED, BASH?删除文件中匹配一个字符串但不匹配另一个字符串的行 - SED,BASH?
【发布时间】:2011-09-25 17:32:57
【问题描述】:

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

如你所知,我是这方面的新手 :(

【问题讨论】:

  • 当您在示例中使用“root”时,请不要在描述中使用“test”。当您在示例中使用“testsh”/“test@”时,请不要在描述中使用“test”/“test@”。请在写问题时更加小心。请问?

标签: linux bash unix sed sh


【解决方案1】:
sed -e '/test/{/test@/!d;}'

第一个模式匹配包含'test'的行;第二个模式删除行,除非它们匹配'test@'。

在数据文件上测试:

aaaa
bbbtestbbb
ccctest@ccc
test!
dddd

输出:

aaaa
ccctest@ccc
dddd

这似乎符合您的要求。

【讨论】:

    【解决方案2】:

    使用grep:

    grep -v 'test[^@]' infile
    

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

    正则表达式匹配任何出现的“test”,其后跟除“@”之外的任何内容。如果您不必期望“测试”出现在行尾,这很好。如果是这种情况,请使用

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

    我认为不值得探讨为什么您的解决方案不起作用,因为它在很多方面都被破坏了。

    【讨论】:

      【解决方案3】:

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

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

      这可以在 awk 中这样完成:

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

      Jonathan's answer 也可以,我只是想给你一个替代版本。

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-17
          • 2017-05-07
          • 2020-04-04
          • 1970-01-01
          相关资源
          最近更新 更多