【问题标题】:Match a pattern, insert the pattern, until next match匹配一个模式,插入模式,直到下一个匹配
【发布时间】:2017-08-10 06:27:26
【问题描述】:

我正在努力使用bash 工具根据所需的输出格式化文件。这是一个示例:

address="192.168.1.1"
portid="443"
portid="2000"
address="192.168.1.2"
portid="443"
portid="2000"

本质上,我想要实现的是搜索一个模式(在这种情况下,整个 IP 地址行),并将其添加到每个后续行,直到下一个匹配项(在下一个 IP 地址之前)。期望的输出是这样的:

address="192.168.1.1"portid="443"
address="192.168.1.1"portid="2000"
address="192.168.1.2"portid="443"
address="192.168.1.2"portid="2000"

如何使用grep、awk 或sed 来实现这一点?

【问题讨论】:

    标签: linux bash awk sed


    【解决方案1】:

    考虑到您的实际文件与显示的示例 Input_file 相同:

    awk '/address/{val=$0;next} {print val $0}'  Input_file
    

    【讨论】:

    • 这是完美的。干净简单。 :)
    • 谢谢 :) 很高兴能帮到你。
    【解决方案2】:

    1. sed

    sed -n 's/address/&/;Ta;h;d;:a;G;s/\(.*\)\n\(.*\)/\2\1/;p' file
    

    诚然,它比 awk 或 perl 更晦涩难懂,这在此处更有意义,并且其代码几乎不言自明。

    s/address/&/;           test (substitute with self) for address
    Ta;                     if false, got to label a
    h;                      (if true) put the line in the hold buffer
    d;                      delete the line from the pattern space
    :a;                     set the label a
    G;                      append the hold buffer to the pattern space (current line)
    s/\(.*\)\n\(.*\)/\2\1/  swap around the newline, so the hold buffer contents
                            are actually prepended to the current line
    p                       print the pattern space
    

    更新:potong 的建议更短更容易理解:

    sed '/^address/h;//d;G;s/\(.*\)\n\(.*\)/\2\1/' file
    

    2。 awk

    awk '/address/{a=$0} /portid/{print a$0}' file
    

    3。 perl

    perl -lane '$a=$_ if /address/;print $a.$_ if /portid/' file
    

    【讨论】:

    • 也许sed '/^address/h;//d;G;s/\(.*\)\n\(.*\)/\2\1/' file 不那么忙了。
    【解决方案3】:

    输入

    [akshay@localhost tmp]$ cat file
    address="192.168.1.1"
    portid="443"
    portid="2000"
    address="192.168.1.2"
    portid="443"
    portid="2000"
    

    输出

    [akshay@localhost tmp]$ awk '/portid/{print a $0; next}/address/{a=$0}' file
    address="192.168.1.1"portid="443"
    address="192.168.1.1"portid="2000"
    address="192.168.1.2"portid="443"
    address="192.168.1.2"portid="2000"
    

    【讨论】:

    • 感谢 Akshay,这看起来确实不错!拯救了我的一天! :)
    • 你应该在某个时候接受一个答案......这是礼貌的做法。而且我也认为它应该是awk 解决方案。在这里说得通。
    • 对不起,史蒂夫,我是新来的,不知道我必须这样做。刚刚做了,谢谢。 :)
    【解决方案4】:

    Sed 答案。必须小心使用货舱空间。

    sed -n -e '/addr/h;/portid/{x;G;s/\nportid/portid/;p;s/portid.*//;h;}'

    解释:

    • sed -n - 仅在明确要求打印时才打印
    • /addr/h - 将地址行保存在保持空间中
    • /portid/{...} - 在匹配 portid 的每一行上,执行以下操作:
      • x 从保持空间中获取 addr 行,将 portid 行放在保持空间中
      • G 将 portid 行附加到 addr 行
      • s/\nportid/portid/ - 删除 portid 行开头的换行符
      • p 打印合并的行
      • s/portid.*// 将端口的东西从组合线上剥离
      • h 再次将 addr 行保存在保持空间中
    • 当然,如果输入真的这么简单,你可以将我使用addr或portid的地方压缩成a和p,但sed已经够神秘了。

    输出:

    $ sed -n -e '/addr/h;/portid/{x;G;s/\nportid/portid/;p;s/portid.*//;h}' addr.txt 地址="192.168.1.1"portid="443" 地址="192.168.1.1"portid="2000" 地址="192.168.1.2"portid="443" 地址="192.168.1.2"portid="2000"

    【讨论】:

      猜你喜欢
      • 2021-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多