【问题标题】:Merging common sections of files in BASH在 BASH 中合并文件的公共部分
【发布时间】:2014-04-20 23:16:03
【问题描述】:

我一直在尝试找到一种方法,以某种方式在每个文件的共同点合并三个文件,我想我会寻求帮助。我的搜索使我了解了从 sed 和 awk 到数组的许多可能的解决方案。 router.txt 文件是骨架文件,我想读入 vars.txt 和 cleanup.txt 以生成一个包含每个部分内容的单个文件。合并后的文件应该包含所有部分,每个文件的每个部分都包含所有相关数据。

我已经尝试了以下数组:

rtimeserver=(`sed -n "/TIME SERVER/,/! -/p" router.txt | sed '/! -/{2,$d}' `)  
vtimeserver=(`sed -n "/TIME SERVER/,/! -/p" vars.txt | sed '/! -/{2,$d}' `)  
cleantimeserver=(`sed -n "/TIME SERVER/,/! -/p" cleanup.txt | sed '/! -/{2,$d}' `)  

通过以下内容,我可以只打印我想要的每个文件的部分。

 printf "%s\n" "${rtimeserver[@]}"  
 printf "%s\n" "${vtimeserver[@]}"  
 printf "%s\n" "${cleantimeserver[@]}"  

但我无法弄清楚如何在路由器文件中找到该部分并从其他文件中滑入这些部分。我想我可以使用 SED 的搜索功能来查找该部分并转储数组内容,但我需要帮助。

非常感谢您愿意提供的任何帮助。
在此先感谢,
迈克

路由器.txt

  !  
  ! ---- NAME SERVER ----  

  ! ---- TIME SERVER ----  
  ntp trusted-key  
  ntp authenticate  
  ntp source Loopback0  
  ! ---- TACACS CONFIG ----  
  !  
  ip tacacs source-interface Loopback 0  
  tacacs-server retransmit 2  
  tacacs-server timeout 2  
  no tacacs-server directed-request  

vars.txt

  ! ---- NAME SERVER ----  
  no ip name-server  
  ip domain-name lab.com  
  ip domain name lab.com  
  ip domain-list lab.com  
  ip domain-list int.lab.com  
  ! ---- TIME SERVER ----  
  ntp server 1.1.1.1  
  sntp server 2.2.2.2  
  ! ---- TACACS CONFIG ----  
  tacacs-server key 1111111111  
  tacacs-server host 1.1.1.1  
  tacacs-server host 1.1.1.2  

清理.txt

  ! ---- NAME SERVER ----  
  no ip dns server-address 3.3.3.3  
  no ip dns server-address 3.3.3.4  
  no ip dns server-address 3.3.3.5  
  ! ---- TIME SERVER ----  
  no clock summer-time  
  sntp poll-interval 65535  
  clock timezone gmt GMT+00  
  ip sntp source-interface loopback 1  
  ! ---- TACACS CONFIG ----  
  tacacs-server host 3.3.3.3  
  tacacs-server host 3.3.3.4  
  tacacs-server host 3.3.3.5  

merged.txt

  ! ---- TIME SERVER ----  
  ntp trusted-key  
  ntp authenticate  
  ntp source Loopback0  
  ntp server 1.1.1.1  
  sntp server 2.2.2.2  
  no clock summer-time  
  sntp poll-interval 65535  
  clock timezone gmt GMT+00  
  ip sntp source-interface loopback 1  

【问题讨论】:

    标签: arrays bash sed awk merge


    【解决方案1】:

    提示:

    awk '
    /! ---/ { p = 0 }        # Disable the flag if lines with header text is seen
    p { lines[++l] = $0 }    # If flag is enabled, populate an array with that line
    /TIME SERVER/ { header = $0; p = 1 }  # Enable the flag when the line with TIME SERVER is seen and capture the line in header variable
    END { 
        print header > "merged.txt"            # Print your header in a new file
        for(line = 1; line <= l; line++)       # Iterate over the array
            print lines[line] >"merged.txt"    # Printing each line in a new file
    }' router.txt vars.txt cleanup.txt
    

    解决方法:

    扩展上面给出的提示,您可以执行以下操作来捕获所有内容:

    awk '
    /! -/ { p = 0 }
        p { lines[seen] = lines[seen] RS $0 }
    /! -/ { seen = $0 ; p = 1}
    END {
        for (line in lines)
            print line, lines[line] > "merged.txt"
    }' router.txt vars.txt cleanup.txt
    

    这将创建一个名为 merged.txt 的新文件,如下所示:

    $ cat merged.txt
    ! ---- NAME SERVER ----
    
    no ip name-server
    ip domain-name lab.com
    ip domain name lab.com
    ip domain-list lab.com
    ip domain-list int.lab.com
    no ip dns server-address 3.3.3.3
    no ip dns server-address 3.3.3.4
    no ip dns server-address 3.3.3.5
    ! ---- TIME SERVER ----
    ntp trusted-key
    ntp authenticate
    ntp source Loopback0
    ntp server 1.1.1.1
    sntp server 2.2.2.2
    no clock summer-time
    sntp poll-interval 65535
    clock timezone gmt GMT+00
    ip sntp source-interface loopback 1
    ! ---- TACACS CONFIG ----
    !
    ip tacacs source-interface Loopback 0
    tacacs-server retransmit 2
    tacacs-server timeout 2
    no tacacs-server directed-request
    tacacs-server key 1111111111
    tacacs-server host 1.1.1.1
    tacacs-server host 1.1.1.2
    tacacs-server host 3.3.3.3
    tacacs-server host 3.3.3.4
    tacacs-server host 3.3.3.5
    

    更新:

    要保留第一个文件的顺序,您可以这样做:

    awk '
    /! -/ { p = 0 }
        p { lines[seen] = lines[seen] RS $0 }
    /! -/ { !($0 in head) ? header[++i]=$0 : x ; p = 1; head[$0]++; seen = $0}
    END {
        for (a=1; a<=i; a++)
            print a, header[a], lines[header[a]]
    }' router.txt vars.txt cleanup.txt
    

    【讨论】:

    • 哇,感谢您的超快响应。你的代码和我希望的完全一样!现在尝试了解它是如何工作的!感谢cmets帮助我理解!
    • @user3422532 我刚刚给出了一个提示,但是由于您承认最佳答案投票,我添加了一个新的解决方案来完全解决您的问题。 :)
    • 这太不可思议了!我很惊讶 AWK 能做到这一点。我过去使用过 AWK,但显然我什至还没有触及它的功能表面!我确实注意到的一件事是,此解决方案将各个部分按不同的顺序排列。再次感谢您提供的出色解决方案,现在是时候回到我的 youtube AWK 视频了!
    • 在尝试将订单恢复到原始文件时,我可以参考任何链接吗?感谢您的帮助!
    • @user3422532 你想要ascending 格式的标题顺序还是它在第一个文件中出现的顺序? This 将是一个很好的起点。
    【解决方案2】:

    使用 awk

    awk 'BEGIN{print "! ---- TIME SERVER ---- "}
    /TIME SERVER/{for (i=2;i<NF;i++) print $i}' FS="\n" RS="! ----" router.txt vars.txt cleanup.txt
    
    ! ---- TIME SERVER ---- 
      ntp trusted-key  
      ntp authenticate  
      ntp source Loopback0  
      ntp server 1.1.1.1  
      sntp server 2.2.2.2  
      no clock summer-time  
      sntp poll-interval 65535  
      clock timezone gmt GMT+00  
      ip sntp source-interface loopback 1
    

    说明

    • FS="\n" RS="! ----"这些是这个awk命令的关键点,正确定义RS和FS以简化过程。

    【讨论】:

      猜你喜欢
      • 2015-12-01
      • 1970-01-01
      • 2020-01-07
      • 1970-01-01
      • 2015-02-27
      • 2013-12-04
      • 1970-01-01
      • 2015-08-24
      • 2021-03-08
      相关资源
      最近更新 更多