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" ]
       for mac in $Vmac
             declare "Vmac${i}"="$mac"
printf "${Vmac1:-NA}"",""${Vmac2:-NA}"",""${Vmac3:-NA}"


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, 2015 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. Mar 13, 2015 at 18:29

1 Answer 1


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" 

To illustrate:

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" 
echo "${vmac[@]}"


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. Mar 13, 2015 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, 2015 at 13:41
  • If you could tell me where I went wrong with my code, that would be a great help too. Mar 13, 2015 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, 2015 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, 2015 at 17:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .