【问题标题】:sed insert a line before the last string in a certain patternsed 在特定模式的最后一个字符串之前插入一行
【发布时间】:2016-12-15 01:16:54
【问题描述】:

我有一个带有行的配置文件:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:sdfilter - [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A sdfilter -j DROP
COMMIT
*nat
:OUTPUT ACCEPT [0:0]
:ds - [0:0]
-A POSTROUTING -o dev -j MASQUERADE
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o dev -j MASQUERADE
COMMIT

我正在尝试在*filter 和第一个COMMIT 之间插入一行-I FORWARD -m physdev --physdev-in eth2 -j DROP,并且只在该模式中的COMMIT 之前插入。所以结果输出看起来像:

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:sdfilter - [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A sdfilter -j DROP
-I FORWARD -m physdev --physdev-in eth2 -j DROP   
COMMIT
*nat
:OUTPUT ACCEPT [0:0]
:ds - [0:0]
-A POSTROUTING -o dev -j MASQUERADE
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o dev -j MASQUERADE
COMMIT

我已经尝试了几种方法,我已经达到的最接近的解决方案是我可以使用 sed 在该模式中的每一行之前追加:

sed '/\*filter/,/COMMIT/i\FORWARD -m physdev --physdev-in eth2 -j DROP' file 

请建议我只能在该过滤模式中的最后一行(“COMMIT”)之前插入的模式?

【问题讨论】:

    标签: awk sed


    【解决方案1】:

    使用awk我可以写,

    /^\*filter$/{found++}
    found && /COMMIT/ {
        print "-I FORWARD -m physdev --physdev-in eth2 -j DROP";
        found=0
    }
    1
    


    什么是?
    • /^\*filter$/{found++} 如果当前行是*filter,则将found 加一。

    • found && /COMMIT/如果当前行有COMMITfilter不为零,

      • 打印我们需要打印的字符串并将found设置为零。
    • 1 这总是正确的,在这种情况下 awk 执行默认任务来打印当前行。


    示例
    $ awk '/^\*filter$/{found++} found && /COMMIT/{print "-I FORWARD -m physdev --physdev-in eth2 -j DROP"; found=0} 1' file
    *filter
    :INPUT DROP [0:0]
    :FORWARD DROP [0:0]
    :OUTPUT ACCEPT [0:0]
    :sdfilter - [0:0]
    -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    -A sdfilter -j DROP
    -I FORWARD -m physdev --physdev-in eth2 -j DROP
    COMMIT
    *nat
    :OUTPUT ACCEPT [0:0]
    :ds - [0:0]
    -A POSTROUTING -o dev -j MASQUERADE
    COMMIT
    *filter
    :PREROUTING ACCEPT [0:0]
    :POSTROUTING ACCEPT [0:0]
    -A POSTROUTING -o dev -j MASQUERADE
    -I FORWARD -m physdev --physdev-in eth2 -j DROP
    COMMIT
    

    【讨论】:

    • 非常感谢您的解决方案。
    【解决方案2】:

    这可能对你有用(GNU sed):

    sed -e '/^\*filter/,/^COMMIT/{/^COMMIT/{i-I FORWARD -m physdev --physdev-in eth2 -j DROP' -e ':a;n;ba}}' file
    

    找到*filterCOMMIT之间的行范围,然后在包含COMMIT的行之前插入所需的字符串,最后打印所有以下行。

    【讨论】:

      【解决方案3】:

      来了sed 答案:

      sed  -n -r '/COMMIT/{x; s/(\*filter.*)/\1\n-I FORWARD -m physdev --physdev-in eth2 -j DROP/;  p; x;p; b end }; H; b; :end n; p; b end'  config_file | sed -e '1d'
      

      --inserted text-- 替换为将附加在第一个 'COMMIT' 之前的文本,plaese。

      说明

      • H 将当前行追加到缓冲区
      • b <label> - 去
      • : <label> - 定义
      • b - 没有简单地结束当前行处理
      • n - 转到下一行
      • x - 交换模式和保持缓冲区(sed 中只有这两个)
      • p - 在屏幕上打印模式缓冲区

      【讨论】:

      • 非常感谢您的解决方案 Marek.. 我唯一担心的是 sed 模式会在文件开头添加新行。请您更正一下。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多