1

I have a variable Vmac that stores values of multiple MAC addresses, collected from wmic call as follows:

Vmac=`wmic --delimiter="," --authentication-file=/path/to/file //IP-ADDR "Select AdapterType,MACAddress from Win32_NetworkAdapter" | grep "Ethernet" | awk -F, '{print $3}'| sort | uniq | tr '\n' ' '`

It has been observed that, the number of values contained in the Vmac variable varies in the range from 1 to 5, for different hosts. I have to separate each of them and store them into a variable VmacN, where N can take values from 1 to 5.

For some hosts, there can be only one MAC Address, so it would have only Vmac1 available. Whereas, host with 4 NICs (and hence MAC Addresses) would have Vmac1, Vmac2, Vmac3 and Vmac4.

In order to tabularize this information efficiently, I also need to store the value NA in the VmacN variables, where less MAC addresses are available (e.g. for machine with 1 NIC, Vmac1 will be AA:BB:CC:DD, while Vmac2 through Vmac5 will be NA. While for machine with 4 NICs, only Vmac5 will be NA).

For this purpose, I created and tested a piece of code, which is as follows:

if [ ! -z "$Vmac" ]
then
        i=1
       for mac in $Vmac
        do
             declare "Vmac${i}"="$mac"
                ((i++))
        done
fi
printf "${Vmac1:-NA}"",""${Vmac2:-NA}"",""${Vmac3:-NA}"

Output:

3C:40:20:52:41:53 88:51:FB:3F:0D:81 C8:CB:B8:CC:5F:D2,NA,NA

When printed only Vmac1, it would print entire MAC addresses (i.e. value of Vmac).

I suppose, I am going wrong in iterating through Vmac.

How to iterate through a variable which holds a string value?

  • 1
    It is not a good idea to declare variable(s) in such way:declare "Vmac${i}"="$mac". Much better use array Vmac[i]=$mac. But if you want you can use eval Vmac$i=\$mac – Costas Mar 13 '15 at 13:08
  • 1
    Nit picks: (1) Rather than sort | uniq, can you use sort -u? (2) Inside `...` or $(...), you don't need | tr '\n' ' ' -- the shell will do that for you, automatically. – Scott Mar 13 '15 at 18:29
4

Just use an array. For example:

## read the MACs into an array
declare -a Vmac=( $(wmic --delimiter="," --authentication-file=/path/to/file \
            //IP-ADDR "Select AdapterType,MACAddress from Win32_NetworkAdapter" | 
             grep "Ethernet" | awk -F, '{print $3}'| sort | uniq | tr '\n' ' ' )

## Add NAs as appropriate
for((i=0;i<6;i++)); do 
    [ -z "${Vmac[i]}" ] && Vmac[i]="NA" 
done

To illustrate:

#!/bin/bash
declare -a vmac=( $(echo 3C:40:20:52:41:53 88:51:FB:3F:0D:81 C8:CB:B8:CC:5F:D2))
for((i=0;i<6;i++)); do 
    [ -z "${vmac[i]}" ] && vmac[i]="NA" 
done
echo "${vmac[@]}"

Output:

3C:40:20:52:41:53 88:51:FB:3F:0D:81 C8:CB:B8:CC:5F:D2 NA NA NA
  • This won't create Vmac1 through Vmac5, but will create Vmac[0] through Vmac[4], if I am not wrong. But, I hope, it will surely fulfill my purpose. I will check and update you. – Mandar Shinde Mar 13 '15 at 13:39
  • @MandarShinde yes, it won't create variables called Vmac1 through 5. That is on purpose. Using such variable names is needlessly complex and, while possible with eval as Costas suggested it will just make your code that much harder to read and that much harder to write. This is precisely what arrays are for. – terdon Mar 13 '15 at 13:41
  • If you could tell me where I went wrong with my code, that would be a great help too. – Mandar Shinde Mar 13 '15 at 13:44
  • 1
    @MandarShinde you were trying to iterate over a string. That won't work. for mac in $Vmac runs once for the entire string, all the MACs saved: f="a b c"; for i in "$f"; do echo $i; done. The spaces are part of the string so you can't iterate over it, it has only a single element, the string itself. – terdon Mar 13 '15 at 13:47
  • 1
    @heemayl none as far as I know. I just added it here to clarify that this is an array. – terdon Mar 13 '15 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.