简体   繁体   English

在bash脚本中使用引号和空格的awk

[英]awk with quotes and spaces in bash script

I've the following output in a bash variable set from a received snmp trap: 我在接收到的snmp陷阱中的bash变量集中输出以下内容:

echo $var echo $ var

Nov 27 16:20:34 witness logger: trap: vars: DISMAN-EVENT-MIB::sysUpTimeInstance = 0:6:10:29.06,  SNMPv2-MIB::snmpTrapOID.0 = SNMPv2-SMI::enterprises.11.2.29.2.90.0.10000002, SNMPv2 SMI::enterprises.11.2.29.2.90.1 = "Finished Number", SNMPv2-SMI::enterprises.11.2.29.2.90.2 = "Filter Cirteria: [called='3333']", SNMPv2-SMI::enterprises.11.2.29.2.90.3 = "Cleared", SNMPv2     SMI::enterprises.11.2.29.2.90.4 = "major Over-Flow alert on Finished Number for ['3333']", SNMPv2 SMI::enterprises.11.2.29.2.90.5 = "The Corresponding Metric Value is: 0.5", SNMPv2- SMI::enterprises.11.2.29.2.90.6 = "Over-Flow", SNMPv2-SMI::enterprises.11.2.29.2.90.7 = "Tue Nov 27 16:20:05 CET 2012" 

I'm trying to get the following output in variables: 我试图在变量中获得以下输出:

var1 = "Tue Nov 27 16:20:05 CET 2012"
var2 = "Finished Number"
var3 = "The Corresponding Metric Value is: 0.5"
var4 = "Cleared"
var5 = "major Over-Flow alert on Finished Number for ['3333']"

I was thinking of doing this via awk 我想通过awk这样做

based on the snmp OID: enterprises.11.2.29.2.90.4, enterprises.11.2.29.2.90.5, 11.2.29.2.90.6 etc... 基于snmp OID:enterprises.11.2.29.2.90.4,enterprises.11.2.29.2.90.5,11.2.29.2.90.6等...

but can't seem to extract just the content of the quoted content " " 但似乎无法仅提取引用内容的内容“”

Perl solution: Perl解决方案:

echo "$var" | perl -nE 'say "var", ++$x, "=$1" while /(".*?")/g'

Output: 输出:

var1="Finished Number"
var2="Filter Cirteria: [called='3333']"
var3="Cleared"
var4="major Over-Flow alert on Finished Number for ['3333']"
var5="The Corresponding Metric Value is: 0.5"
var6="Over-Flow"
var7="Tue Nov 27 16:20:05 CET 2012"

It seems that you want to match all the strings inside double quotes, which is easiest done with grep : 看起来你想要匹配双引号内的所有字符串,这是用grep最简单的方法:

$ echo $var | grep -o '"[^"]*"'

"Finished Number"
"Filter Cirteria: [called=3333]"
"Cleared"
"major Over-Flow alert on Finished Number for [3333]"
"The Corresponding Metric Value is: 0.5"
"Over-Flow"
"Tue Nov 27 16:20:05 CET 2012"

Explanation: 说明:

-o only print the part of the line that matches. -o只打印匹配行的部分。

"     # Match opening double quote
[^"]* # Match anything not a double quote
"     # Match closing double quote

Hope this helps you get started. 希望这有助于您入门。

Let's start with something simple so you can see how the fields would be broken down when you use awk : 让我们从一些简单的东西开始,这样你就可以看到当你使用awk时字段会被分解:

echo "${var}" | awk 'BEGIN{FS="\""} {for (i=1; i<=NF; i++) {print "["i"]", $i}}'

Or, if your shell supports herestrings: 或者,如果你的shell支持herestrings:

awk 'BEGIN{FS="\""} {for (i=1; i<=NF; i++) {print "["i"]", $i}}' <<< "${var}"

Output: 输出:

[1] Nov 27 16:20:34 witness logger: trap: vars: DISMAN-EVENT-MIB::sysUpTimeInstance = 0:6:10:29.06,  SNMPv2-MIB::snmpTrapOID.0 = SNMPv2-SMI::enterprises.11.2.29.2.90.0.10000002, SNMPv2 SMI::enterprises.11.2.29.2.90.1 = 
[2] Finished Number
[3] , SNMPv2-SMI::enterprises.11.2.29.2.90.2 = 
[4] Filter Cirteria: [called='3333']
[5] , SNMPv2-SMI::enterprises.11.2.29.2.90.3 = 
[6] Cleared
[7] , SNMPv2     SMI::enterprises.11.2.29.2.90.4 = 
[8] major Over-Flow alert on Finished Number for ['3333']
[9] , SNMPv2 SMI::enterprises.11.2.29.2.90.5 = 
[10] The Corresponding Metric Value is: 0.5
[11] , SNMPv2- SMI::enterprises.11.2.29.2.90.6 = 
[12] Over-Flow
[13] , SNMPv2-SMI::enterprises.11.2.29.2.90.7 = 
[14] Tue Nov 27 16:20:05 CET 2012
[15]  

Now choose the fields as required: 现在根据需要选择字段:

var1=$(awk 'BEGIN{FS="\""} {print $14}' <<< "${var}")
var2=$(awk 'BEGIN{FS="\""} {print $2}' <<< "${var}")
var3=$(awk 'BEGIN{FS="\""} {print $10}' <<< "${var}")
var4=$(awk 'BEGIN{FS="\""} {print $6}' <<< "${var}")
var5=$(awk 'BEGIN{FS="\""} {print $8}' <<< "${var}")

Explanation: 说明:

  • awk 'BEGIN{FS="\\""} : Here we use awk to delimit the input on " awk 'BEGIN{FS="\\""} :这里我们使用awk来分隔输入"
  • {print $14}' : Print the specific field enclosed by quotes {print $14}' :打印引号括起来的特定字段
  • <<< "${var}" : Use herestring instead of echo if available (see above) <<< "${var}" :如果可用,使用herestring而不是echo(见上文)
  • This is under the assumption that the format of your $var stays relatively consistent with regard to field ordering 这是假设$var的格式在字段排序方面保持相对一致
$ echo "$var" | awk -F\" 'BEGIN{n=split("14 2 10 6 8",v," ")} {for (i=1;i<=n;i++) printf "var%d = \"%s\"\n",i,$(v[i])}'
var1 = "Tue Nov 27 16:20:05 CET 2012"
var2 = "Finished Number"
var3 = "The Corresponding Metric Value is: 0.5"
var4 = "Cleared"
var5 = "major Over-Flow alert on Finished Number for ['3333']"

Also, maybe more what you want, here's how to populate a shell array with the result of the awk execution: 另外,也许更多你想要的,这里是如何使用awk执行的结果填充shell数组:

$ IFS=$'\n' varArr=( $(echo "$var" | awk -F\" 'BEGIN{n=split("14 2 10 6 8",v," ")}
 {for (i=0;i<=n;i++) printf "\"%s\"\n",$(v[i])}') )

$ echo "${varArr[1]}"                                                         
"Tue Nov 27 16:20:05 CET 2012"

$ echo "${varArr[2]}"
"Finished Number"

$ echo "${varArr[3]}"
"The Corresponding Metric Value is: 0.5"

$ echo "${varArr[4]}"
"Cleared"

$ echo "${varArr[5]}"
"major Over-Flow alert on Finished Number for ['3333']"

and if you don't want the quotes around your text, just don't add them in the awk script: 如果您不想在文本周围添加引号,请不要在awk脚本中添加它们:

IFS=$'\n' varArr=( $(echo "$var" | awk -F\" 'BEGIN{n=split("14 2 10 6 8",v," ")}
{for (i=0;i<=n;i++) print $(v[i])}') )

Both of the above will put the entire input string in ${varArr[0]}. 以上两个都将整个输入字符串放在$ {varArr [0]}中。 It's a trivial tweak if that's undesirable. 如果那是不可取的,这是一个微不足道的调整。

I ended up using the awk solution, but the others were well suited also. 我最终使用awk解决方案,但其他人也非常适合。 Thanks to all. 谢谢大家。

val=$(echo $val |  awk '{for(i=1;i<=NF;i++)if($i~/is:/)print $(i+1)}' | cut -d\" -f 1)

For info the script is used in snmptrapd when a trap is received it puts logs in the messages and performs other actions on particular alarms. 有关信息,当收到陷阱时,脚本将在snmptrapd中使用,它会将日志放入消息中,并对特定警报执行其他操作。

The main loop is as follows: 主循环如下:

vars=
while read oid val
do
if [ "$vars" = "" ]
  then
    vars="$oid = $val"
  else
    vars="$vars, $oid = $val" 
        if [ "$oid" == "SNMPv2-SMI::enterprises.11.2.29.2.90.5" ]
        then
          val=$(echo $val |  awk '{for(i=1;i<=NF;i++)if($i~/is:/)print $(i+1)}' | cut -d\" -f 1)
          /bin/logger "found: value 5:    $val "
          val5=$val
        fi
 fi
done

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM