【问题标题】:Append two new lines before additional text using sed使用 sed 在附加文本前追加两行
【发布时间】:2013-12-05 04:58:02
【问题描述】:

我遇到了一些困难(对我来说)。我试图在我们的服务器构建过程中(使用 kickstart 安装后脚本)在 RHEL5 /etc/sysconfig/iptables 文件中插入两个换行符。

具体的sed命令是:

${SED} -i "/-i lo/ a\
\n\n#Trusted Traffic\n-A INPUT -s 10.153.156.0/25,10.153.174.160/27 -d ${MGTIP} -m state --state NEW -j ACCEPT\n\n#Remote Access\n-A INPUT -s 10.120.80.0/21,10.152.80.0/21,10.153.193.0/24,172.18.1.0/24,${MGTNET}/${NUMBITS} -d ${MGTIP} -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n\n#Backups\n-A INPUT -s 10.153.147.192/26 -d ${BKPIP} -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n\n" ${IPTABLES}

这实际上是更大脚本的一部分。 ${SED} 和 ${IPTABLES} 已设置为必要的值。

除前两个换行符外,所有换行符都有效。或者,更准确地说,是前两个中的第二个。即使是 ACCEPT 之后的最后两个换行符也有效。前两个换行符发生的情况是第一个有效,在匹配包含-i lo 的 iptables 条目后创建一个换行符。然而,第二个只是在 #Trusted Traffic 文本之前插入一个文字“n”。

它最终看起来像

(snip)
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
n#Trusted Traffic
-A INPUT (snip)

我尝试了各种方法来确保插入第二个换行符。我使用了两个空行而不是\n\n。我在不同的行上使用了两个换行符,我使用了\\n\\n。到目前为止,我尝试过的所有结果都相同:插入文字 'n' 而不是第二个换行符。

sed 是否不能在附加文本的开头使用两个换行符?有没有办法让我完全不知道这项工作?

【问题讨论】:

    标签: regex bash sed


    【解决方案1】:

    有趣的是,我原以为您尝试的解决方案之一会起作用,但我看到了相同的行为。这是一种可能的解决方案:

    ${SED} -i -e "s/-i lo.*/\0\n\n/" -e "// a\
    #Trusted Traffic\n-A INPUT -s 10.153.156.0/25,10.153.174.160/27 -d ${MGTIP} -m state --state NEW -j ACCEPT\n\n#Remote Access\n-A INPUT -s 10.120.80.0/21,10.152.80.0/21,10.153.193.0/24,172.18.1.0/24,${MGTNET}/${NUMBITS} -d ${MGTIP} -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n\n#Backups\n-A INPUT -s 10.153.147.192/26 -d ${BKPIP} -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n\n" ${IPTABLES}
    

    首先将两个换行符附加到上一行的末尾,然后进行附加。

    【讨论】:

    • 我可能偶然发现了一个错误?还是只是一个未记录的“功能”? ;)
    • 它引用了整个匹配。不确定是否所有版本的 sed 都支持此功能,您可能需要使用 s/\(-i lo.*\)/\1\n\n/
    • 您使用 \0 的解决方案不起作用。它吐出/bin/sed: can't read s/-i lo.*/\0\n\n/: No such file or directory; /bin/sed: -e expression #1, char 0: no previous regular expression。我怀疑第二个错误仅仅是因为第一个错误。我将尝试使用 \1 并会报告。
    • 我怀疑下面答案中的问题是我在使用这两种解决方案时遇到的问题。
    【解决方案2】:

    我不明白为什么它也不起作用,但您也可以使用替代选项而不是附加选项来做到这一点:

    ${SED} -i "s%-i lo.*%&\n\n#Trusted Traffic\n-A INPUT -s 10.153.156.0/25,10.153.174.160/27 -d ${MGTIP} -m state --state NEW -j ACCEPT\n\n#Remote Access\n-A INPUT -s 10.120.80.0/21,10.152.80.0/21,10.153.193.0/24,172.18.1.0/24,${MGTNET}/${NUMBITS} -d ${MGTIP} -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n\n#Backups\n-A INPUT -s 10.153.147.192/26 -d ${BKPIP} -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT\n\n%" ${IPTABLES}
    

    【讨论】:

    • 试过这个解决方案。我收到/bin/sed: -e expression #1, char 646: unknown option to 's'。该行位置 646 处唯一的东西是“A”。上下文:<text>...\n-A INPUT...<text>.
    • 哦,对不起,您的替换文本中有很多/,我没有尝试使用您的全文并错过了。我现在使用% 作为s 命令的分隔符,而不是全部转义它们。可以再试一次吗?
    • 当然。我也错过了。甚至不记得所有的 CIDR 斜线。我想这首先是问题所在。
    【解决方案3】:

    不确定可移植性,但请尝试:

    ${SED} '/-i lo/ a\
    \
    \
    '"#Trusted Traffic\\
    -A INPUT -s 10.153.156...
    "
    

    这种技术适用于 BSD sed。您可以在整个过程中使用双引号:

    ${SED} "/-i lo/ a\\
    \\
    \\
    #Trusted Traffic\\
    -A INPUT -s 10.153.156...
    "
    

    在任何一种情况下,反斜杠和行尾之间都不能有空格。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      • 2014-04-12
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多