Reputation: 510
I've the following output in a bash variable set from a received 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'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
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...
but can't seem to extract just the content of the quoted content " "
Upvotes: 4
Views: 567
Reputation: 510
I ended up using the awk solution, but the others were well suited also. 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.
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
Upvotes: 0
Reputation: 203254
$ 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:
$ 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:
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]}. It's a trivial tweak if that's undesirable.
Upvotes: 1
Reputation: 85775
It seems that you want to match all the strings inside double quotes, which is easiest done 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
only print 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.
Upvotes: 3
Reputation: 47267
Let's start with something simple so you can see how the fields would be broken down when you use 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 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 "
{print $14}'
: Print the specific field enclosed by quotes<<< "${var}"
: Use herestring instead of echo if available (see above)$var
stays relatively consistent with regard to field orderingUpvotes: 2
Reputation: 241808
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"
Upvotes: 3