【问题标题】:sed : delete all lines NOT containing string A or B, starting at 2nd linesed :从第 2 行开始删除所有不包含字符串 A 或 B 的行
【发布时间】:2017-09-15 13:10:18
【问题描述】:

请帮忙 - 我卡住了。

我需要

  1. 删除文本文件的所有行
  2. 不包含 foo 或 Foo
  3. 从文件的第二行开始

infile

first line 
foobar 
tree 
fish
Foo Bar
Football
Foobar
Street
foo bar

输出文件

first line
foobar
Foo Bar
Football
Foobar
foo bar

我尝试了以下方法:

sed '2,$/*.foo.*\|.*Foo.*/!d' -i test.txt

产生的错误是:

sed:-e 表达式#1,字符 4:未知命令:`/'

我的错误是什么? (awk 也是一个可能的替代方案。)

【问题讨论】:

  • 您的2nd 是什么意思?你能澄清一下吗
  • 具有预期输出的示例文件应该是强制性的。
  • 为什么足球不是输出的一部分?
  • 抱歉,确实复制了错误的内容。现已更正。

标签: bash awk sed


【解决方案1】:

sed 方法:

sed -e '2,${/[fF]oo/!d}' file

-e 脚本 (--expression=script)

script 中的命令添加到要在同时运行的命令集中 处理输入。

2,$ - 地址范围,考虑从第二行到末尾的行

[fF] - 字符类,匹配 fF

/!d - 删除不包含fooFoo 的行

【讨论】:

  • 我也误解了这个问题,OP想要删除不包含 foo 或 Foo 的行
  • @ZumodeVidrio,是的,有一些令人困惑的时刻
  • 可能是sed '1!{/[fF]oo/!d}' file?
  • @potong,对于简单的情况 - 是的。在“动态”范围的情况下,地址范围将更加灵活
【解决方案2】:
awk 'NR==1 || !/foo|Foo/' oldfile > newfile

注意:如果使用 csh 或 tcsh,则需要用反斜杠保护!

awk 'NR==1 || \!/foo|Foo/' oldfile > newfile

【讨论】:

  • 详情awk 'NR==1 || !/[fF]oo/' oldfile > newfile
【解决方案3】:

一个不错的选择是颠倒您的要求 - 删除所有行,但打印第一行和所有带有 foo 或 Foo 的行。

sed -n '1p; /foo\|Foo/p'

如果第一行包含 foo 或 Foo,它将打印两次,但如果需要,可以轻松修复。

【讨论】:

    【解决方案4】:

    有机会但没有sed 也没有awk(不知道它们是否在您的情况下是强制性的),您可以将文本文件的第一行复制到一个新文件中:

    head -1 textfile > newfile
    

    然后您可以将所有带有 foo 或 Foo 的内容附加到新文件中:

    grep "foo\|Foo" textfile >> newfile
    

    因此您将在 newfile 中获得所需的内容。

    如果你想把它放在你的原始文件中,那么你可以移动它:

    mv newfile textfile
    

    如果第一行包含 foo 或 Foo 它将被打印两次,但正如你所说的你想保留第一行,我假设它不会既没有 foo 也没有 Foo。

    【讨论】:

    • 其实第一行在newfile中会出现两次
    【解决方案5】:

    在 awk 中。首先是一些测试数据:

    $ cat file
    1 begin
    2 asd
    3 foo
    4 sdf
    5 Foo
    6 end
    

    代码。在包含fooFoo 的第一条记录之后的print 记录:

    $ awk 'NR==1 || /[fF]oo/' file
    1 begin
    3 foo
    5 Foo
    

    【讨论】:

    • OP 先询问所有问题 :-)
    • @NeronLeVelu 我注意到,在 cmets 中抱怨,沮丧并放弃了。不是我的日子。固定。
    • @James Brown 很抱歉一开始没有正确描述输入/输出!现在添加了一些有问题的数据。谢谢!
    【解决方案6】:

    森林里的另一个 awk

    awk '!a++||!/[fF]oo/' infile
    

    【讨论】:

      【解决方案7】:

      这是您的代码:

      sed '2,$/*.foo.*\|.*Foo.*/!d'
      

      这里的问题是您使用了两种形式的行寻址,即数字 (addr1,addr2) 和匹配 (/REGEX/)。另外,你的正则表达式有错误。

      这是我的解决方法:

      sed '1b; /[fF]oo/!d' infile
      

      输出:

      first line
      foobar 
      Foo Bar
      Football
      Foobar
      foo bar
      

      【讨论】:

      • POSIX 版本(非 GNU sed):sed -e '1b' -e '/[Ff]oo/!d' infile
      • 非常感谢您的回答,托尔!完美运行!
      【解决方案8】:
      awk '/^[fF]/&&!/fish/' file
      
      first line
      foobar
      Foo Bar
      Football
      Foobar
      foo bar
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-21
        • 2020-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-28
        • 2015-11-24
        • 1970-01-01
        相关资源
        最近更新 更多