transpose sets of three rows to columns

I have a file that has below entries:

[[email protected] ovm_utils]# cat /tmp/disk.txt
Physical Disk : 'IBM (67) device=/dev/mapper/360050768018206483000000000000453 shareddisk=true
Physical Disk : 'IBM (58) device=/dev/mapper/36005076801820648300000000000043f shareddisk=true
Physical Disk : 'IBM (59) device=/dev/mapper/360050768018206483000000000000440 shareddisk=true
Physical Disk : 'IBM (71) device=/dev/mapper/360050768018206483000000000000497 shareddisk=true
[[email protected] ovm_utils]#

I tried using sed and awk in all possible way which I am aware of but couldn’t get it in the required format. I would like to have the file in this format:

Physical Disk  device                                          Shareddisk
IBM (67)        /dev/mapper/360050768018206483000000000000453  true
IBM (58)        /dev/mapper/36005076801820648300000000000043f  true
IBM (59)        /dev/mapper/360050768018206483000000000000440  true
IBM (71)        /dev/mapper/360050768018206483000000000000497  true

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Using awk variables and multiple matches you can read each line, store what you need and then print on the last match and start over.

#!/usr/bin/awk -f

BEGIN {
  DISK=""
  DEVICE=""
  FS=" : "
  print "Physical Disk\tdevice\t\t\t\t\t\tShareddisk"
  }

/Physical Disk/ {
  DISK=$2
  FS="="
}

/device/ {
  DEVICE=$2
}

/shareddisk/ {
  print DISK "\t" DEVICE "\t" $2
  FS=" : "
  }

Then run the script against your file awk -f ./script.awk ./disk.txt

$ awk -f ./parse.awk ./disk.txt
Physical Disk   device                                          Shareddisk
'IBM (67)       /dev/mapper/360050768018206483000000000000453   true
'IBM (58)       /dev/mapper/36005076801820648300000000000043f   true
'IBM (59)       /dev/mapper/360050768018206483000000000000440   true
'IBM (71)       /dev/mapper/360050768018206483000000000000497   true

To break down the script, it starts with a BEGIN block which is run at the start. It defines some variables and sets the Field Separator FS and prints the header. The first match is for Physical Disk and stores the disk name to a variable. The Field Separator is changed to = since the Device and Shared Disk lines use =. When the line matching /shareddisk/ is hit the variables are printed and the Field Separator is changed again to match the next Physical Disk line.

Edit

This assumes the format of the file is:

cat disk.txt
Physical Disk : 'IBM (67)
  device=/dev/mapper/360050768018206483000000000000453
  shareddisk=true
Physical Disk : 'IBM (58)
  device=/dev/mapper/36005076801820648300000000000043f
  shareddisk=true
Physical Disk : 'IBM (59)
  device=/dev/mapper/360050768018206483000000000000440
  shareddisk=true
Physical Disk : 'IBM (71)
  device=/dev/mapper/360050768018206483000000000000497
  shareddisk=true

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply