Bash
將多個變數設置為 awk 輸出的不同欄位
我有大量的變數初始化,我認為可以大大減少。下面被解析的文件:
-------------------- ACL Stats Per Interface ---------------------- Entries Packets Dropped Recent Total PerMax Recent Total PerMax Slot 0 /Port 0 Trusted 1 196 1311578 386 0 0 0 Untrusted 3 20 217217953 852794 0 0 0
…腳本中的程式碼片段如下:
expect_results="stats.txt" acl_stats_per_interface_trusted_entries_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $2}' ` acl_stats_per_interface_trusted_recent_packets_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $3}' ` acl_stats_per_interface_trusted_total_packets_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $4}' ` acl_stats_per_interface_trusted_permax_packets_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $5}' ` acl_stats_per_interface_trusted_dropped_recent_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $6}' ` acl_stats_per_interface_trusted_dropped_total_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $7}' ` acl_stats_per_interface_trusted_dropped_permax_s0_p0=`grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted" | awk '{print $8}' `
而不是
grep
ping 同一個文件 7 次,有沒有辦法 grep 一次並將這些變數設置為每個單獨的awk
輸出?
FWIW 我只是使用 awk 從輸入文件中提取文本以及值並將其輸出列印到 .prom 文件,而無需手動創建一堆 shell 變數等:
$ cat tst.awk $1 ~ /^-+$/ { # -------------------- ACL Stats Per Interface ---------------------- gsub(/^[[:space:]]*-+[[:space:]]+|[[:space:]]+-+[[:space:]]*$/,"") fileHdr = $0 next } /^[[:space:]]/ { if (NF == 3) { # Entries Packets Dropped colName[1] = $1 for (i=2; i<=NF; i++) { colHdr[i] = $i } } else { # Recent Total PerMax Recent Total PerMax for (i=1; i<=3; i++) { colName[i+1] = $i "_" colHdr[2] } for (; i<=NF; i++) { colName[i+1] = $i "_" colHdr[3] } } next } /^Slot/ { # Slot 0 /Port 0 slot = $2 port = $NF next } /^[[:alpha:]]/ { # Trusted 1 196 1311578 386 0 0 0 # Untrusted 3 20 217217953 852794 0 0 0 rowName = $1 for (i=2; i<=NF; i++) { out = tolower(fileHdr "_" rowName "_" colName[i-1] "_s" slot "_p" port) "=" $i gsub(/[[:space:]]+/,"_",out) print out } }
$ awk -f tst.awk file acl_stats_per_interface_trusted_entries_s0_p0=1 acl_stats_per_interface_trusted_recent_packets_s0_p0=196 acl_stats_per_interface_trusted_total_packets_s0_p0=1311578 acl_stats_per_interface_trusted_permax_packets_s0_p0=386 acl_stats_per_interface_trusted_recent_dropped_s0_p0=0 acl_stats_per_interface_trusted_total_dropped_s0_p0=0 acl_stats_per_interface_trusted_permax_dropped_s0_p0=0 acl_stats_per_interface_untrusted_entries_s0_p0=3 acl_stats_per_interface_untrusted_recent_packets_s0_p0=20 acl_stats_per_interface_untrusted_total_packets_s0_p0=217217953 acl_stats_per_interface_untrusted_permax_packets_s0_p0=852794 acl_stats_per_interface_untrusted_recent_dropped_s0_p0=0 acl_stats_per_interface_untrusted_total_dropped_s0_p0=0 acl_stats_per_interface_untrusted_permax_dropped_s0_p0=0
如果您有工俱生成與您發布的輸入文件格式相同的其他文件,那麼上面的 awk 腳本也應該適用於它們,無需為它們創建專門的 shell 腳本。對於其他格式的輸入文件,您可以調整腳本以使用相同的方法。
您可以使用
read
內置函式讀取一行並將多個值分配給變數。錯誤處理和較短變數名稱的範例:
if read dummy var1 var2 var3 var4 var5 var6 var7 extra then echo OK else echo EOF fi < <(grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted") if [ -n "$extra" ] then echo too many values fi if [ -z "$var7" ] then echo not enough values fi echo vars: $var1 $var2 $var3 $var4 $var5 $var6 $var7
或更短,沒有錯誤處理
read dummy var1 var2 var3 var4 var5 var6 var7 extra < <(grep -A 2 "Slot 0 /Port 0" $expect_results | grep "Trusted") echo vars: $var1 $var2 $var3 $var4 $var5 $var6 $var7
該程式碼期望您的輸入由單行組成,其中包含由空格分隔的簡單值,沒有嵌入空格、特殊字元、引號……
要了解 EOF 或錯誤數量的值的錯誤處理,請閱讀
read
內置文件,例如此處https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.htmlEOF 的特定錯誤處理似乎沒有必要。
read
在這種情況下(在我的系統上)所有變數都是空的,但我在內置的文件中沒有找到這種行為的規範。在輸入中找不到匹配行時會發生 EOF。