【问题标题】:sed two pattern search and append line after the last occurence of the second patternsed 两个模式搜索并在第二个模式最后一次出现后追加行
【发布时间】:2013-02-28 10:43:07
【问题描述】:

在过去的 2 天里,以下sed 问题一直让我很头疼。

我有以下文件(iptables)

someline

someline

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

someline

我想使用sed 搜索模式*filter,如果匹配则搜索第二个模式[0:0],然后在第二个模式的最后一次出现后添加一行。

这将(理想情况下)导致:

someline

someline

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

TESTLINEADDEDBYSED

someline

这里的论坛给了我一个好的开始,但我就是无法解决这个特定的问题。

到目前为止,我有以下解决方案,但它在第二个模式[0:0] 的第一次出现之后添加了行:

sed -n '/\*filter/{:a;N;/^\n/s/^\n//;/\[0:0\]/{!ba;p;s/.*/TESTLINEADDEDBYSED/;};ba}; p' file

我假设在第二个分支中使用.* 我会消耗(阅读:跳过?)[0:0] 的第一次出现? 我在这里误会了什么?

【问题讨论】:

    标签: linux unix sed awk grep


    【解决方案1】:

    这个怎么样:

    fgrep -q '*filter' file && tac file|awk '!f&&/\[0:0\]/{$0="FOO\n\n"$0;f=1}1'|tac
    someline
    
    someline
    
    *filter
    
    :INPUT ACCEPT [0:0]
    
    :FORWARD ACCEPT [0:0]
    
    :OUTPUT ACCEPT [0:0]
    
    FOO
    
    someline
    

    第一个fgrep 用于file 中的固定字符串*filter,如果找到,则在包含[0:0] 的最后一行之后插入行FOOtac 用于反向读取文件,因此您无需读取文件两次或缓冲即可找到最后一次出现,因为更容易找到第一次出现。


    如果文件的大小不是很大,使用awk 的两遍方法:

    awk 'FNR==NR{if($0~/*filter/)a=1;if(a&&$0~/\[0:0\]/)b=NR;next}FNR==b{$0=$0"\n\nFOO"}1' file file
    
    someline
    
    someline
    
    *filter
    
    :INPUT ACCEPT [0:0]
    
    :FORWARD ACCEPT [0:0]
    
    :OUTPUT ACCEPT [0:0]
    
    FOO
    
    someline
    

    【讨论】:

    • 虽然我的第一个想法是只使用 sed,但我必须承认我也喜欢这种简单而优雅的方法。谢谢!
    • 有时链接现有实用程序可能是一种更简单的方法,我在我的答案中添加了一个仅使用 awk 的两遍方法以进行对比。
    【解决方案2】:

    略有不同的方法,因为sed 换行很糟糕......

    基本上,我将所有内容放在一行中,用@ 替换换行符,使用贪婪匹配进行替换,最后将换行符重新放回原处...

    $ cat input | tr '\n' '@' | sed s'/\(\*filter.*\[0:0\]\)/@@\1@TESTLINEADDEDBYSED/' | tr '@' '\n'
    someline
    
    someline
    
    
    *filter
    
    :INPUT ACCEPT [0:0]
    
    :FORWARD ACCEPT [0:0]
    
    :OUTPUT ACCEPT [0:0]
    
    TESTLINEADDEDBYSED
    
    someline
    

    如果文件中的行数很大,这是一种不好的方法!

    【讨论】:

    • 所以答案在于制作一个大行(带有分隔符),然后编辑该行,然后再将其分成多行?很有意思!谢谢!!
    • @sudo_O - 好痛!我通常是处理 UUoC 奖的人:-)
    • @cybernijntje - 很高兴你喜欢它。不要忘记投票:-)
    • @Fredrik haha​​ ;) 不要忘记 OP 代表还不够高,无法投票!
    • @sudo_O - 是的。 +1 即使我受伤了,你也要坚强
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 2017-01-25
    相关资源
    最近更新 更多