【问题标题】:Use SED to produce a specific format from values in a text file (line by line)使用 SED 从文本文件中的值生成特定格式(逐行)
【发布时间】:2021-03-31 07:34:22
【问题描述】:

我有一个 ports.txt 文件,其中包含以下数据“IP 地址、本地端口、远程端口和协议”。这是文件的样子:

1.1.1.1-22-2222-tcp
2.2.2.2-3000-4321-udp
3.3.3.3-80-8080-tcp
4.4.4.4-443-4443-tcp

我想做的是使用 SED 通过将 ports.txt 文件中的值放在正确的位置来编辑每一行。

我使用了 ports.txt 文件中的第 1 行作为预期结果的示例:

-A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 1.1.1.1:22

我发现我可以使用这样的循环逐行读取:

while read line; do echo $line; done < ports.txt

但我不知道如何让 SED 提取值并将它们放入所需的格式。

【问题讨论】:

    标签: linux string shell csv sed


    【解决方案1】:

    使用 awk,将字段分隔符设置为 -,然后以所需格式使用字段进行打印。

    awk -F- '{ print "A PREROUTING -i eth0 -p "$4" -m "$4" --dport "$3" -j DNAT --to-destination "$1":"$2 }' ports.txt
    

    【讨论】:

      【解决方案2】:

      下面的解决方案使用echosedtailgrep来提取端口、协议和目标。

      对于目的地:我们从末尾删除端口和协议,然后用破折号 (-) 替换冒号 (:)。 (另外,作为预防措施,尾随空格也被考虑在内)。

      对于协议:我们只是删除直到最后的 - 之前的所有内容,以及任何尾随空格以防万一。

      对于端口:我们使用grep 来查找所有数字序列,-o 只给我们匹配组件,然后我们使用tail -1 提取最后一个匹配项。

      : '
      INPUT:
      1.1.1.1-22-2222-tcp
      2.2.2.2-3000-4321-udp
      3.3.3.3-80-8080-tcp
      4.4.4.4-443-4443-tcp
      
      OUTPUT:
      -A PREROUTING -i eth0 -p tcp -m tcp --dport 2222 -j DNAT --to-destination 1.1.1.1:22
      -A PREROUTING -i eth0 -p udp -m udp --dport 4321 -j DNAT --to-destination 2.2.2.2:3000
      -A PREROUTING -i eth0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 3.3.3.3:80
      -A PREROUTING -i eth0 -p tcp -m tcp --dport 4443 -j DNAT --to-destination 4.4.4.4:443
      '
      
      while read -r line
      do
          dest=$(echo "$line" | sed 's/-[^-]*-[^-]*\s*$//;s/-/:/')
          protocol=$(echo "$line" | sed 's/.*-//;s/\s*$//')
          port=$(echo "$line" | grep -oE '[0-9]+' | tail -1)
          echo "-A PREROUTING -i eth0 -p $protocol -m $protocol --dport $port -j DNAT --to-destination $dest"
      done < ports.txt
      

      【讨论】:

      • 这个答案也非常感谢你,但我注意到协议被永久设置为 tcp。
      • 不错的 @confused,它现在也插入了协议
      【解决方案3】:

      使用这个 Perl 单行代码:

      perl -F'-' -lane 'my ( $ip_address, $local_port, $remote_port, $protocol ) = @F; print "-A PREROUTING -i eth0 -p tcp -m ${protocol} --dport ${remote_port} -j DNAT --to-destination ${ip_address}:${local_port}";' ports.txt
      

      Perl 单行程序使用这些命令行标志:
      -e:告诉 Perl 查找内联代码,而不是在文件中。
      -n:循环输入一行一次,默认将其分配给$_
      -l:在执行内联代码之前剥离输入行分隔符(默认为 *NIX 上的"\n"),并在打印时附加它。-a :在空格或-F 选项中指定的正则表达式上将$_ 拆分为数组@F
      -F'-' :在破折号(-)上拆分为@F,而不是在空白处。

      另请参阅:
      perldoc perlrun: how to execute the Perl interpreter: command line switches

      【讨论】:

      • 没想到要用perl,多谢回答
      【解决方案4】:

      使用 sed:

      sed -rn 's/(^.*)-(.*)-(.*)-(.*$)/A PREROUTING -i eth0 -p \4 -m \4 --dport \3 -j DNAT --to-destination \1:\2/p' ports.txt
      

      将行拆分为用 - 分隔的各个部分,并将行替换为以所需格式打印的不同部分(用 \n 指定)。

      【讨论】:

      • 请注意,这不是返回正确的端口号。应该是--dport \3
      • 好点@costaparas 我已经修改了
      • 你们的大脑都有行星那么大!非常感谢您的快速回复:)
      猜你喜欢
      • 1970-01-01
      • 2011-01-07
      • 2020-11-28
      • 1970-01-01
      • 2021-07-28
      • 1970-01-01
      • 2021-09-19
      • 2023-03-04
      相关资源
      最近更新 更多