Bianca-Elena Duduman
Bianca-Elena Duduman

Reputation: 23

How do I extract the UUID for a specific VM and Group with awk?

I am using vboxmanage list -l vms and I want to extract the UUID for a specific machine by giving the Name and Groups values.

Name:                        vm2
Groups:                      /C05Lab1
Guest OS:                    Oracle (64-bit)
UUID:                        54c233e8-3d5b-46bb-9a21-a8946ffa7d76
Config file:                 C:\Users\Bianca\VirtualBox VMs\C05Lab1\vm2\vm2.vbox
Snapshot folder:             C:\Users\Bianca\VirtualBox VMs\C05Lab1\vm2\Snapshots
Log folder:                  C:\Users\Bianca\VirtualBox VMs\C05Lab1\vm2\Logs
Hardware UUID:               54c233e8-3d5b-46bb-9a21-a8946ffa7d76

I got to:

vboxmanage list -l vms | awk '$1=="UUID:"{uid=$2} /Name: *vm2/{print uid}'

It at least lists an uuid, but not the right one(it prints the uuid of the machine before it) and I have no idea how to check for the Groups value because it starts with a /

Upvotes: 2

Views: 213

Answers (2)

RavinderSingh13
RavinderSingh13

Reputation: 133760

With your shown samples, please try following awk code.

vboxmanage list -l vms | 
awk -v name="vm2" -v group="C05Lab1" '
/^Name:/{
  foundName=foundGroup=""
  if($2==name){ foundName=1 }
  next
}
/^Groups:/ && $2==group{
  foundGroup=1
  next
}
/^UUID:/ && foundName && foundGroup{
  print
  foundName=foundGroup=""
}'

Explanation: Adding detailed explanation here.

vboxmanage list -l vms |               ##Running command vboxmanage list -l vms and sending its Output to awk as an input.
awk -v name="vm2" -v group="C05Lab1" ' ##Starting awk command from here and setting name to vm2 and group to C05Lab1 here.
/^Name:/{                              ##Checking condition if line starts with Name: then do following.
  foundName=foundGroup=""              ##Nullifying foundName and foundGroup here.
  if($2==name){ foundName=1 }          ##Checking condition if 2nd field is name then set foundName to 1 here.
  next                                 ##next will skip all further statements from here.
}
/^Groups:/ && $2==group{               ##Checking condition if line starts from Groups: and 2nd field is group then do following.
  foundGroup=1                         ##Setting foundGroup to 1 here.
  next                                 ##next will skip all further statements from here.
}
/^UUID:/ && foundName && foundGroup{   ##Checking condition if line starts from UUID: and foundName and foundGroup are set then do following.
  print                                ##Printing currnet line here.
  foundName=foundGroup=""              ##Nullifying foundName and foundGroup here.
}'

EDIT by Ed Morton to show an alternative approach to commenting the code, i.e. commenting to say why we're doing things instead of what we're doing:

vboxmanage list -l vms |
awk -v name="vm2" -v group="C05Lab1" ' # Set variables to contain the Name: and Groups: values we want to find in the input
/^Name:/{                              # We assume that every record starts with Name: and so we clear the
  foundName=foundGroup=""              # foundName and foundGroup flags here so that when we hit the UUID:
                                       # line later they arent still set from reading the previous record.
  if($2==name){ foundName=1 }          # If the current value of the Name: matches the target value stored in
                                       # our "name" variable then set the flag to indicate that so when we test
                                       # it on our UUID: line we know we found the target name.
  next
}
/^Groups:/ && $2==group{               # If the current value of the Group: matches the target value stored in
  foundGroup=1                         # our "group" variable then set the flag to indicate that so when we test
                                       # it on our UUID: line we know we found the target group.
  next
}
/^UUID:/ && foundName && foundGroup{   # Were on the UUID: line from the input so if we had previously found
  print                                # our target "name" and "group" as indicated by the 2 flags we set earlier
                                       # then we output the current line which contains the UUID.
  foundName=foundGroup=""              # Clear foundName and foundGroup flags here to ensure that when we hit the UUID:
                                       # line for the next record they arent still set from reading the current record
}'

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 204558

Any time you have tag-value pairs in your input it's best to first create an array to hold those values indexed by their tags (aka keys aka names), e.g. f[] below, and then you can just access the values by their tags to easily compare, print, modify, reorder, etc. as you like:

$ cat tst.awk
{
    tag = val = $0
    sub(/:.*/,"",tag)
    sub(/[^:]+:[[:space:]]*/,"",val)
    f[tag] = val
}
(tag == "UUID") && (f["Name"] == name) && (f["Groups"] == groups) {
    print val
}

$ awk -v name='vm2' -v groups='/C05Lab1' -f tst.awk file
54c233e8-3d5b-46bb-9a21-a8946ffa7d76

Upvotes: 1

Related Questions