【问题标题】:Using sed to remove all lines after last time specific string is mentioned in TXT在 TXT 中最后一次提到特定字符串后,使用 sed 删除所有行
【发布时间】:2020-08-13 01:24:15
【问题描述】:

我有一个如下所示的文件:

Apple prices
$15.74 p 12
$13.17 p 12
$8.19 p 8
Apple prices
$12.99 p 11
$4.67 p 1
$3.22 p 2
Apple prices
$3.99 p 1
$4.65 p 2
$2.19 p 1

我想要一个单行 sed 命令,它可以在最后一次提到“Apple 价格”之后删除所有内容。所以结果是:

Apple prices
$15.74 p 12
$13.17 p 12
$8.19 p 8
Apple prices
$12.99 p 11
$4.67 p 1
$3.22 p 2

在 sed 中,我尝试使用 '/Apple prices/q2',但这会在第一次提及而不是最后一次之后删除所有内容。

有没有办法让它只在最后一次使用 sed 提到它之后删除所有内容?

【问题讨论】:

    标签: ubuntu sed replace


    【解决方案1】:

    问题在于 sed 不知道“Apple 价格”的出现是否是最后一次,直到它到达另一个 - 或文件末尾。但它可以在 Hold Space 中收集行并推迟决定:

    sed -n '/Apple prices/{x;/./p;d;};H'
    

    编辑: 受@potong 评论启发的替代方案:

    sed '/Apple prices/!{H;d;};x;1d;'
    

    【讨论】:

    • 我喜欢这个解决方案,特别是因为它在模式/保持空间之间翻转。如果我要挑剔,我更喜欢b而不是d,因为不使用-n选项的双重解决方案是sed '/Apple/{x;/./p;d};H;d' file
    • @potong:我给你一个更好的;见上面的编辑。也可以使用b 而不使用holdspace,但我认为它会同样神秘。
    • 完美,正是我需要的。谢谢!
    • 我的卑微努力不使用保持空间sed '/\n/{:a;P;D};:b;$d;N;/\n.*Apple prices/ba;bb' file 很可能是 GNU 特定的。顺便说一句,虽然它不适用于此实例,但如果有其他水果价格,可能会出现一个极端情况,并且需要在 H 命令之后添加一个附加命令 1h,以防止在开头出现不需要的换行符输出。
    • @potong:非常聪明!这是我既不使用保持空间也不使用测试/分支的可耻不谦虚的努力:sed '/\nApple prices/{P;D;};N;s/^/\[NEWLINE]/;D' filename 其中[NEWLINE] 是一个实际的换行符(因为我知道没有更简洁的方法来使用替换命令插入换行符)。
    【解决方案2】:

    在这种情况下,一种常见的策略是逐行反转输入,根据第一次出现做出决定,然后再次反转输出

    $ # with awk: tac ip.txt | awk 'f; /Apple prices/{f=1}' | tac
    $ tac ip.txt | sed '0,/Apple prices/d' | tac
    Apple prices
    $15.74 p 12
    $13.17 p 12
    $8.19 p 8
    Apple prices
    $12.99 p 11
    $4.67 p 1
    $3.22 p 2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多