簡體   English   中英

bash腳本抓取屏幕輸出並解析為csv

[英]bash script to grab screen output and parse to csv

當我運行一個名為chk的自定義腳本並將其輸出到csv時,我正在編寫一個bash腳本來獲取屏幕輸出。

chk命令的屏幕輸出示例

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

我的命令$ line可以是任何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

接下來我想在腳本中輸入一個項目列表($ line)我想運行自定義腳本並將每個屏幕輸出解析為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

它的工作或多或少,但有兩件事我有困難。

  1. 如何在我的最終腳本中包含csv文件標題,而shell腳本中的循環不會一直重寫標題(您會注意到我將標題從我當前的腳本awk命令中刪除)。 使用NR == 1也會覆蓋我需要的屏幕輸出中的第一行

  2. 如何使用命令args指定輸出csv文件的名稱。 我試圖重定向到>> $ 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-consideration-bad-practice ) ,和
  2. 你現在在chk的所有調用的輸出上運行awk一次,而不是每次單獨調用chk運行awk一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM