sed在特定模式中的最后一个字符串之前插入一行

时间:2016-12-13 10:19:18

标签: awk sed

我有一个包含行的配置文件:

    /**
     * Returns <tt>true</tt> if this list contains the specified element.
     * More formally, returns <tt>true</tt> if and only if this list contains
     * at least one element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o element whose presence in this list is to be tested
     * @return <tt>true</tt> if this list contains the specified element
     */
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    /**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     */
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

我试图在*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 和第一个-I FORWARD -m physdev --physdev-in eth2 -j DROP之间插入一行*filter,并且只在该模式中的COMMIT之前插入。所得到的输出如下所示:< / p>

COMMIT

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

*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

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

3 个答案:

答案 0 :(得分:0)

使用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

答案 1 :(得分:0)

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'

- 插入的文字替换为首先在'COMMIT'之前附加的文字,plaese。

<强>解释

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

答案 2 :(得分:0)

这可能适合你(GNU sed):

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

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