Bash

將多個變數設置為 awk 輸出的不同欄位

  • December 9, 2020

我有大量的變數初始化,我認為可以大大減少。下面被解析的文件:

                  -------------------- 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}' `

而不是grepping 同一個文件 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.html

EOF 的特定錯誤處理似乎沒有必要。read在這種情況下(在我的系統上)所有變數都是空的,但我在內置的文件中沒有找到這種行為的規範。在輸入中找不到匹配行時會發生 EOF。

引用自:https://unix.stackexchange.com/questions/623638