Bash : More parameter expansion and IFS

I am trying to become more fluent with the interworking of bash and minimize the number of external calls.

Sample Data. This will be the response of the snmp query.

SNMPv2-MIB::sysName.0 = STRING: SomeHostName
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.9.1.1745
SNMPv2-MIB::sysDescr.0 = STRING: Cisco IOS Software, IOS-XE Software, Catalyst L3 Switch Software (CAT3K_CAA-UNIVERSALK9-M), Version 03.06.08.E RELEASE SOFTWARE (fc1)

I would like to extract as follows:

sysD=03.06.08.E 
sysN=SomeHostName
sysO=1745

The code given below does this. But its ugly and is very dependant on external calls.

I reviewed Chris FA Johnsons site / link Extracting parts of a string by Chris F.A. Johnson and reviewed a few books I have written by him and looked at web resources and dont find a good method to execute the same without external calls.

Is there anyway I can isolate these pieces of information without external calls ?

 
sult=$($SNMPG $RW -v2c -mALL $i sysDescr.0 sysName.0 sysObjectID.0 2>/dev/null)
sysD=$(echo "$sult" | grep "sysDescr" | sed 's/.*, Version //g; s/ RELEASE.*//g; s/,$//g')
sysN=$(echo "$sult" | grep "sysName" | awk '{print $NF}')
sysO=$(echo "$sult" | grep "sysObjectID" | sed 's/.*enterprises//g' | cut -d"." -f4)
printf "%s," "$sysN" "$sysD" "$sysO";printf "%s\n" | tee -a ofil.csv

Thanks for all your help !!

How about

while read line
  do    [[ "$line" =~ sysName ]]         && sysN=${line##* }
        [[ "$line" =~ sysObjectID ]]     && sysO=${line##*.}
        [[ "$line" =~ sysDescr ]]        && { TMP=${line##*Version }; sysD=${TMP%% RELEASE*}; }
  done <<< $($SNMPG $RW -v2c -mALL $i sysDescr.0 sysName.0 sysObjectID.0 2>/dev/null)
 echo $sysD, $sysO, $sysN
03.06.08.E, 1745, SomeHostName
1 Like

bash supports regex, tried that?

string="SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.9.1.1745"
regex1="sysObjectID"
regex2="[0-9]{4}$"
if [[ "$string"  =~ $regex1 ]] then 
   [[ "$string" =~ $regex2 ]] then
      echo "matched part is ${BASH_REMATCH[1]}"
   fi
fi

Edit: Rudi beat me to it.

1 Like

As general note - some bash regex strings fail when used directly on the command line. Spaces in regex are an example.
It is probably best practice to make them variables:
bash - Capturing Groups From a Grep RegEx - Stack Overflow
Dennis Williamson's answer comment section

1 Like

Tsch .. thanks. You guys are wizards :slight_smile: !

Cant quite put it all together. Maybe someday when I grow up Ill be a wizard too !!

Thanks fellas !!

---------- Post updated at 02:10 PM ---------- Previous update was at 01:56 PM ----------

... lightning fast too !

If I see many if [[ $var in a row then it's time to think of a case-esac.
But it uses a whole line glob match, not a regular expression.
Here a leading and trailing * allow preceding and succeeding characters (while a regular expression does not need leading/trailing .* )

while read line
do
  case $line in
  (*sysName*) sysN=${line##* } ;;
  (*sysObjectID*) sysO=${line##*.} ;;
  (*sysDescr*) TMP=${line##*Version }; sysD=${TMP%% RELEASE*} ;;
  esac
done < <($SNMPG $RW -v2c -mALL $i sysDescr.0 sysName.0 sysObjectID.0 2>/dev/null)
printf "%s,%s,%s\n" "$sysN" "$sysD" "$sysO"

I also replaced the "herestring made of a command substitution" <<< $( ) by a "process substitution" < <( ) .

2 Likes