我有一大堆变量初始化,我认为可以大大减少。正在解析的文件如下:
-------------------- 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
办法对同一个文件执行 7 次 ping 操作,而只进行一次 grep 并将这些变量设置为每个单独的awk
输出?
答案1
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 脚本。对于其他格式的输入文件,您可以调整脚本以使用相同的方法。
答案2
您可以使用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。
答案3
我选择将grep
语句的输出读入数组,并单独访问这些元素,而不是实例化这么多变量。
acl_stats_trusted=( $(grep "Trusted" "$expect_results") )
echo "${acl_stats_trusted[1]}" # Outputs 1
echo "${acl_stats_trusted[3]}" # Outputs 1311578
这对于任何用户来说都更加简洁和清晰。