繁体   English   中英

使用 shell 脚本解析 Yml 文件(awk、sed、grep、...)

[英]Yml file parsing with shell scripting ( awk, sed, grep , ... )

此时初始解析数据后的脚本输出是这样的

  - hostname: lfpm9001
        - id: 700
          addr: 100.241.50.118/28
        - id: 800
          addr: 10.241.50.161/28
  - hostname: lfpm9002
        - id: 355
          addr: 100.243.52.129/25
        - id: 228
          addr: 100.241.51.161/25
        - id: 190
          addr: 100.245.25.1/24       
  - hostname: lfpm9003
        - id: 400
          addr: 100.250.55.121/24
        - id: 600
          addr: 100.242.56.168/28
        - id: 185
          addr: 100.240.26.10/24

尝试将此文件转换为 output 中的这样:


lfpm9001     700      100.241.50.118   28

lfpm9001     800      10.241.50.161    28

lfpm9002     355      100.243.52.129   25

lfpm9002     288      100.241.51.161   25

lfpm9002     190      100.245.25.1     24   

lfpm9003     400      100.250.55.121   24

lfpm9003     600      100.242.56.168   28

lfpm9003     185      100.240.26.10    24

试过这个,部分解决了问题,但无法根据需要捕获主机名。

sed -E '/-/{N;s~[^0-9]*([0-9]+)\n[^0-9]*([0-9.]+)/([0-9]+)~\1,\2,\3~}'

使用 GNU sed

$ sed -E '/hostname/{s/[^:]*: ([[:alnum:]]+)/\1/;h;d};N;G;s~[^:]*id: ([0-9]*)\n[^:]*: ([0-9.]*)/([0-9]*)(.*)~\4\t\1\t\2\t\3~' input_file

lfpm9001        700     100.241.50.118  28

lfpm9001        800     10.241.50.161   28

lfpm9002        355     100.243.52.129  25

lfpm9002        228     100.241.51.161  25

lfpm9002        190     100.245.25.1    24

lfpm9003        400     100.250.55.121  24

lfpm9003        600     100.242.56.168  28

lfpm9003        185     100.240.26.10   24

awk进场

输入文件有以hostname-keyed记录,每条记录后跟任意数量的包含关联数据的记录对。

下面的awk过程有三个action块,每个块都有针对特定行的pattern条件。

第一个块针对在其第 3 个field ( $3 ) 中包含字符串“主机名”的行。 它捕获与名为host的变量中的主机名键关联的值。 它还将名为ln的行号变量设置为输入文件的当前record (行)号:

/hostname/{host=$3; ln=NR}

第二个块通过引用存储在第一个块中的行号ln来定位下一行。 它构造一个存储在名为line的变量中的字符串,其中包含存储的主机名、制表符和包含id值的字段 3。

NR==ln+1 {line=host"\t"line"\t"$3}

第三个块针对包含 IP 数据的下一行。 它将字段$2中的 IP 值拆分为斜线,将这些部分存储在一个名为IP的双元素数组中,使用这些部分在打印该行之前继续 output 字符串(并添加一个新行以实现您的空白行所需的输出)。

最后,第三个块将line变量重置为空字符串,并将包含主机名的行的存储值增加 2。 最后一步将第二个和第三个块应用于接下来的两行,前提是它们不是包含主机名的行(在这种情况下,行号将在块 1 内重置以重新启动循环)。

NR==ln+2 {split($2,IP,"/");line=line"\t"IP[1]"\t"IP[2]; print line"\n"; line=""; ln=ln+2}

整个awk程序

awk '/hostname/{host=$3; ln=NR} NR==ln+1 {line=host"\t"line"\t"$3} NR==ln+2 {split($2,IP,"/");line=line"\t"IP[1]"\t"IP[2]; print line"\n"; line=""; ln=ln+2}' inputFile

测试

在 gnu awk 5.1.0 API 上测试:3 在 Raspberry Pi 400 上。

output:

lfpm9001        700 100.241.50.118  28

lfpm9001        800 10.241.50.161   28

lfpm9002        355 100.243.52.129  25

lfpm9002        228 100.241.51.161  25

lfpm9002        190 100.245.25.1    24

lfpm9003        400 100.250.55.121  24

lfpm9003        600 100.242.56.168  28

lfpm9003        185 100.240.26.10   24

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM