Home > Net >  Yml file parsing with shell scripting ( awk, sed, grep , ... )
Yml file parsing with shell scripting ( awk, sed, grep , ... )

Time:11-30

The out put of the script after initial parsing data is like this at this point

  - 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

trying to convert this file to have like this in 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

Tried this, and partially solved the issue but can't capture hostname as desired.

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

CodePudding user response:

Using 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

CodePudding user response:

awk approach

The input file has hostname-keyed records, each followed by any number of pairs of records containing associated data.

The following awk procedure has three action blocks, each with pattern conditions targeting particular lines.

The first block targets lines containing the string "hostname" in their 3rd field ($3). It captures the value associated with the hostname key in a variable named host. It also sets a line number variable named ln to the current record (line) number of the input file:

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

The second block targets the next line by referencing the line number ln, stored in the first block. It constructs a string stored in a variable named line with the stored host name, a tab delimeter, and field 3, containing the id value.

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

The third block targets the next line containing the IP data. It splits the IP value held in field $2 at he slash, storing the parts in a two-element array named IP, using the parts to continue the output string before printing the line (and adding a new line to achieve the blank line in your required output).

Lastly, the third block resets the line variable to an empty string and advances the stored value of the line containing the hostname by two. This last step applies the second and third blocks to the next two lines providing they are not hostname-containing lines (in which case the line number will be reset within block 1 to restart the cycle).

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

The entire awk procedure

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

Test

tested on gnu awk 5.1.0 API: 3 on 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
  • Related