bash脚本抓取屏幕输出并parsing为csv

我正在编写一个bash脚本来抓取屏幕输出,当我运行一个名为chk的自定义脚本并将其输出到csv。

chk命令的屏幕输出示例

type: ISDSL ACCESS ADSL circt: 219317638 speed: 4096 rroutr: Billion 7404 (IS) intr: 196.214.12.124/30 vrf: PCTPT 

我的命令$行可以是任何linetag

 chk $line | egrep 'type|circt|speed|rroutr|intr|vrf' | awk'{if(NR==1){print " Circuit,Speed,CE,,WAN IP,VRF";} else{print $2 $3} ORS=","}' 

这是输出

 Circuit,Speed,CE,,WAN IP,VRF 219317638,4096,Billion,196.214.12.124/30,PCTPT 

在这之后,我想input到脚本的项目列表($行)我想要运行自定义脚本并parsing每个屏幕输出到CSV文件。

 # This script takes in a file of many $line's and runs the chk command on each line usage ./parsechk2csv <filename> #!/bin/bash cat $1|while read line; do echo "$line\n"; chk $line | egrep 'type|circt|speed|rroutr|intr|vrf' | awk'{if(NR==1) {print "";}else{print $2 $3} ORS=","}' >> test.csv done 

它的工作或多或less,但有两件事我有困难。

  1. 如何在我的最终脚本中包含csv文件标题,而shell脚本中的循环始终不变地重写标题(您将注意到我将标题从我当前的脚本awk命令中删除)。 使用NR == 1也会覆盖我需要的屏幕输出中的第一行

  2. 如何使用命令args指定输出csv文件的名称。 我试图redirect到>> $ 3.csv,但这是行不通的。

它不清楚你的输入文件的哪一行映射到输出中的哪些字段,因为你显示的值对于标题行中的名字似乎没有意义,但是这是如何做到你想要的:

 $ cat file first linetag type: ISDSL ACCESS ADSL circt: 219317638 speed: 4096 routr: ctn3-dsl/e0 rroutr: Billion 7404 (IS) intr: 196.214.12.124/30 vrf: first idk second linetag type: Next fake ACCESS circt: 123456 speed: 2020 routr: foo-hspd/e1 rroutr: dozens 6564 (IS) intr: 100.200.30.304/27 vrf: second idk 

 $ cat tst.sh #infile="$1" #outfile="${2:-test.csv}" #<"$infile" xargs -d'\n' -n1 -Iline sh -c 'echo "line"; chk "line"' | cat file | awk -v RS= -F'\n' -v OFS="," ' BEGIN { split("LineTag,Router,Type,Circuit,Speed,PE,WANIP,VRF",names,/,/) split("linetag,routr,type,circt,speed,rroutr,intr,vrf",abbrs,/,/) } NR==1 { for (i=1; i in names; i++) { printf "%s%s", (i>1?OFS:""), names[i] } print "" } { delete abbr2value abbr2value[abbrs[1]] = $1 for (i=2; i<=NF; i++) { abbr = value = $i sub(/:.*/,"",abbr) sub(/[^:]+:[[:space:]]*/,"",value) abbr2value[abbr] = value } for (i=1; i in abbrs; i++) { printf "%s%s", (i>1?OFS:""), abbr2value[abbrs[i]] } print "" }' #}' >> "$outfile" 

 $ ./tst.sh LineTag,Router,Type,Circuit,Speed,PE,WANIP,VRF first linetag,ctn3-dsl/e0,ISDSL ACCESS ADSL,219317638,4096,Billion 7404 (IS),196.214.12.124/30,first idk second linetag,foo-hspd/e1,Next fake ACCESS,123456,2020,dozens 6564 (IS),100.200.30.304/27,second idk 

只要用脚本开头的当前注释掉的行代替cat file (它只是用来模拟两次运行chk的输出,以演示awk脚本的工作情况),并在末尾替换}'与当前注释}' >> "$outfile"并根据您的意思更改split()命令中字段的顺序。

请注意,以上与你今天的重大差异是:

  1. 您不再有明确的shell循环,而是使用xargs遍历输入文件的内容(请参阅为什么这很重要,为什么是使用-hell-loop-to-process-text-considered-bad-practice ) ,和
  2. 现在,您可以在chk的所有调用的输出上运行一次awk,而不是每次单独调用chk都运行一次awk。