【问题标题】:Insert a string on line after a match ignoring lines with a #在匹配后插入一个字符串,忽略带 # 的行
【发布时间】:2018-02-02 08:01:01
【问题描述】:

这可能会很困难。

我需要一种通过 bash 脚本向 Apache2 配置文件添加别名的方法。

我已经用 grep 检查别名是否已在另一个配置文件中使用。我现在面临的问题是如何将“ServerAlias testing.com”添加到配置文件中。

每个配置文件都有两个虚拟主机,分别为端口 80 和端口 443。

我需要将字符串“ServerAlias testing.com”添加到“ServerName”之后下一行的每个配置中,但忽略以 # 或 ; 开头的任何行。

例子:

<VirtualHost *:80>

    # A comment with ServerName in it <-- must be ignored

    ServerName test.com
    <<ADD STRING HERE>> 

</VirtualHost>
<VirtualHost *:443>

    ServerName test.com
    <<AND HERE>>

</VirtualHost>

任何帮助将不胜感激。

编辑: 必须忽略注释,因为 apache 上的默认配置有我希望保留的 cmets,并且在这些 cmets 中是必须忽略的“ServerName”,每个虚拟主机只会有一个“ServerName”。

虚拟主机标签对我来说无关紧要,只要我可以忽略 cmets 并在每个虚拟主机配置中的 ServerName 之后添加一次 ServerAlias testing.com 就行了。

这需要对配置进行编辑,然后保存到文件

【问题讨论】:

  • 您真正想添加什么,ServerAlias testing.comServerName 'test.com'?您正在谈论两者(也请注意引号)。
  • 所有排序现在:-) 需要添加ServerAlias testing.com
  • 所以我的下一个问题是,如果有任何评论,或者您不想打印该评论,您想跳过整个区块吗?您能否更具体地回答您的问题?
  • 如果ServerName 可以出现在您文件中的其他任何地方,而您希望它被更改,那么将这些情况包含在您的示例输入/输出中。在文件中查找目标字符串是微不足道的,在各种上下文中包含/排除相同的目标字符串是事情变得更有趣的地方。现在,您有不同的人对 VirtualHost 文本是否相关做出不同的假设,如果是,那么通过说明它们是否是您查找 ServerName 的要求的一部分并包括相关的内容,以什么方式消除所有混淆示例输入/输出中的示例
  • 还有一个事实是您的新字符串包含与现有字符串(包括“test.com”)相关的任何方式的“testing.com”?

标签: bash awk sed printf


【解决方案1】:

另一种awk方法:

awk '/^ *ServerName test.com/{s=substr($0,1,index($0,"S")-1)"ServerAlias testing.com"; 
     printf "%s\n%s\n", $0,s; next }1' file

输出:

<VirtualHost *:80>

    # A comment with ServerName in it <-- must be ignored

    ServerName test.com
    ServerAlias testing.com

</VirtualHost>
<VirtualHost *:443>

    ServerName test.com
    ServerAlias testing.com

</VirtualHost>

其他sed方法:

sed -i 's/^\( *\)\(ServerName test.com\)/\1\2\n\1ServerAlias testing.com/' file

【讨论】:

  • 如何输出到文件
  • @Dan,使用我的第二种方法就地修改文件
【解决方案2】:

尝试关注,如果这对您有帮助,请告诉我。

awk '/<\/VirtualHost>/{a=""} /VirtualHost/{a=1} a && $1~/ServerName/ && $2 ~ /test.com/{print $0 RS "    ServerAlias " s1 "testing.com" s1;next} 1 ' s1="'"  Input_file

EDIT1: 由于 OP 想要忽略 cmets 并将其保存到 Input_file 本身,因此请尝试以下操作。

awk '/^#/{next} /<\/VirtualHost>/{a=""} /VirtualHost/{a=1} a && $1~/ServerName/ && $2 ~ /test.com/{print $0 RS "    ServerAlias " s1 "testing.com" s1;next} 1 ' s1="'"  Input_file > temp && mv temp Input_file

【讨论】:

  • 这里,插入也可以发生在&lt;VirtualHost&gt;...&lt;/VirtualHost&gt; 块之外。
  • @Anubis,现在相应地编辑代码,谢谢。
  • @Anubis 希望他在他的示例中包含一个他不想在目标字符串之后添加新字符串的情况,如果他的输入中可能存在这种情况,但我想我们'看看OP怎么说...
  • @Dan 你说I need to add ... after 'ServerName test.com'。如果不是这样,请编辑您的问题以说明您的实际要求。
  • @Anubis OP 刚刚更新了问题,说虚拟主机的东西是无关紧要的。
【解决方案3】:
$ awk '{print} /^[[:space:]]*ServerName/{sub(/[^[:space:]].*/,"ServerAlias testing.com"); print}' file
<VirtualHost *:80>

    # A comment with ServerName in it <-- must be ignored

    ServerName test.com
    ServerAlias testing.com

</VirtualHost>
<VirtualHost *:443>

    ServerName test.com
    ServerAlias testing.com

</VirtualHost>

请注意,它使用前一行中存在的任何缩进来缩进新字符串。

【讨论】:

  • 这是否会忽略以 # 开头的行,因为它最终可能会在注释后的行上添加 ServerAlias testing.com
  • 废话,我现在看到你只选择前面有空格的行
  • 如何输出到文件
  • 就像将任何命令的输出保存到文件一样,在命令行末尾添加&gt; outputfile。如果您想更改原始文件,则使用任何给定命令(awk、sed、grep 等)您只需执行command file &gt; tmp &amp;&amp; mv tmp file,因此在这种情况下为awk '...script...' file &gt; tmp &amp;&amp; mv tmp file
  • @Dan 您收到了对您的问题的多个答案 - 请参阅 stackoverflow.com/help/someone-answers 了解下一步该做什么。
【解决方案4】:
sed '/<VirtualHost \*:\(80\|443\)>/{
    :a;
    n;
    /<\/VirtualHost>/!{
        /^\(\s*#.*\|\s*\)$/ba;
        s/\(\s*\)ServerName test.com/&\n\1ServerAlias testing.com/;
        ba; 
    };
}' <input_file_path

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多