Awk with quotes and spaces in a bash script

I have the following output in a bash variable set from the resulting snmp trap:

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 am trying to get the following result 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 thought about it through awk

based on ODM snmp: enterprises .11.2.29.2.90.4, enterprises .11.2.29.2.90.5, 11.2.29.2.90.6, etc.

but it may not seem that it only extracts the contents of the quoted content ""

+4
source share
5 answers

It seems that you want to combine all the lines inside double quotes, which is easiest to do with 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 print only the part of the line that matches.

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

Hope this helps you get started.

+3
source

Perl Solution:

 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" 
+3
source

Let's start with something simple so you can see how the fields are broken when using awk :

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

Or if your shell supports 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 select the required fields:

 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 input to "
  • {print $14}' : print a specific field enclosed in quotation marks
  • <<< "${var}" : use herestring instead of echo if available (see above)
  • This is done under the assumption that the format of your $var remains relatively consistent in relation to the ordering of the fields.
+2
source
 $ 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, perhaps more of what you want here is how to populate a shell array with the result of awk execution:

 $ 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 need quotes around your text, just don't add them to awk script:

 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 put the entire input string in $ {varArr [0]}. This is a trivial setting if this is undesirable.

+1
source

In the end, I decided to use an awk solution, but others were fine. Thanks to everyone.

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

For information, the script is used in snmptrapd when it receives a trap, it puts the logs in messages and performs other actions on specific alarms.

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 
0
source

All Articles