将多个变量设置为 awk 输出的不同字段

将多个变量设置为 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办法对同一个文件执行 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

这对于任何用户来说都更加简洁和清晰。

相关内容