有没有一种简单的方法可以等效于`sed ...` 用多个值替换同一行?

Ale*_*lke 5 sed array shell-script text-processing template

我有一个文件,我想用 shell 脚本中的数据替换一些变量

-A INPUT -i lo -s @LOCAL_IP@ -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

这里我想用IP地址替换@LOCAL_IP@,我使用以下内容:

... | sed -e 's/@LOCAL_IP@/192.168.1.1/' | ...
Run Code Online (Sandbox Code Playgroud)

我的 shell 脚本中的变量中可能有 192.168.1.1,但这是提供基本思路。

现在,我有另一个规则,如下所示:

-A INPUT -i @PUBLIC_INTERFACE@ -p tcp -m tcp --dport 22
            -d @PUBLIC_IP@ -s @ADMIN_IPS@ --syn -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

(这是一条很长的行,为了便于阅读,在此处分解)

真正的输入文件将是输入文件中的许多行,大多数没有@ADMIN_IPS@,例如:

-A INPUT -i @PUBLIC_INTERFACE@ -p tcp -m tcp --dport 80 -d @PUBLIC_IP@ --syn -j ACCEPT
-A INPUT -i @PUBLIC_INTERFACE@ -p tcp -m tcp --dport 22 -d @PUBLIC_IP@ -s @ADMIN_IPS@ --syn -j ACCEPT
-A INPUT -i @PUBLIC_INTERFACE@ -p tcp -m tcp --dport 443 -d @PUBLIC_IP@ --syn -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我可以轻松替换@PUBLIC_INTERFACE@ 和@PUBLIC_IP@。这与之前的行相同。但是,@ADMIN_IPS@ 是一个包含 2 个或 3 个 IP 地址的列表。结果应该是这样的:

-A INPUT -i eth0 -p tcp -m tcp --dport 80 -d 8.8.8.8 --syn -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -d 8.8.8.8 -s 8.8.10.1 --syn -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -d 8.8.8.8 -s 8.8.10.2 --syn -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -d 8.8.8.8 -s 8.8.10.3 --syn -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -d 8.8.8.8 --syn -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

是否有一种相对简单的方法可以使用sedLinux等工具将单行转换为多行?(Ubuntu 16.04) 在这种情况下,三个ADMIN_IPS地址将在一个变量中定义,如下所示:

ADMIN_IPS=8.8.10.1,8.8.10.2,8.8.10.3
Run Code Online (Sandbox Code Playgroud)

它也可以是空间分隔的,甚至是一个数组。

Jef*_*ler 3

这是一个丑陋的 awk 解决方案;其他人可能有更聪明的方法来做到这一点:

awk -v pi=1.2.3.4 -v pint=eth0 -v pip=8.8.8 -vaips="8.8.10.1 8.8.10.2 8.8.10.3"  \
  'BEGIN{
        split(aips, array)
   }
   {
        gsub(/@PUBLIC_INTERFACE@/, pint);
        gsub(/@PUBLIC_IP@/, pi);
        if (/@ADMIN_IPS@/) {
                copy=$0
                for (i in array)  {
                  gsub(/@ADMIN_IPS@/, array[i], copy)
                  print copy
                  copy=$0
                }
        } else {
          print;
        }
   }' input
Run Code Online (Sandbox Code Playgroud)

这会将变量传递到 awk(对管理 IP 使用空格分隔);在读取任何输入之前,awk 会将传入的“数组”拆分为名为 的真实 awk 数组array。对于每一行输入,awk 将全局搜索并替换各种单例变量,然后如果该行中存在 @ADMIN_IPS@,则对管理 IP 进行循环并打印出具有相应管理 IP 的输入行的副本更换。