Format output into columns, variables with multiple entries

Hello all, I've got a script that collects data on file systems and prints out specific data about each. I've formatted headers w/ printf like so.

printf "\033[4mVolume Name\tDisk\t\tBlock Device\t\t\t\tMount Point\t\tSize\tOwnership\033[0m\n"

and I had the content of the varibles printed out beneath those columns like so:

printf "${volume}\t${diskvol}\t${blockdevice}\t\t${mntpnt}\t\t${fssize}\t${owner}\n"

The problem I've run into is that should one of those variables contain multiple entries if ruins the formatting. I've experimented with printf and to attempt to overcome it but I'm not successful thus far.

The code I have at the moment is below.

printf "%-5s%-10s%-15s%-10s%-5s" ${volume} ${diskvol} ${blockdevice} ${mntpnt} ${fssize} ${owner}

actual output of the script attached.

Essentially the headers are fine. Its the data that follows that has no spacing and isnt respecting the "spaces" i defined.

Help appreciated

Add a "\n" to the end of the printf statement, and use double quotes around each variable.

Is this what youre expecting? I have something very similar in my first post but I edited it per your specs.

printf "${volume}\t${diskvol}\t${blockdevice}\t\t${mntpnt}\t\t${fssize}\t${owner}\n"

to this?

printf "${volume}"\t "${diskvol}"\t"${blockdevice}"\t\t"${mntpnt}"\t\t"${fssize}"\t"${owner}""\n"

If I have my code matching what you expected to see then it clobbers the formatting again. See attachment.

Expanding shell variables directly within a printf format string is a bad idea; it sh it can lead to unpredictable behavior (in C, it's a serious security hole) if something in those variables resembles a format specifier (%s, %d, %%, etc).

No offense, but I cannot be bothered to analyze your output and reverse engineer the values of your variables.

You should show us the code you are using in its entirety or at the very least print out the value of each variable for each line of output. Then the actual output for those values followed by the desired output.

Regardless of any of the above, your format will be wrecked if any string exceeds its alloted width unless the format specifier truncates it by specifying a precision. In case it's illuminating compare this ...

$ printf '%4s %4s\n' col1 col2 ---- ---- 1234567890 1234567890
col1 col2
---- ----
1234567890 1234567890

against this ...

$ printf '%4.4s %4.4s\n' col1 col2 ---- ---- 1234567890 1234567890
col1 col2
---- ----
1234 1234

If your output format must accommodate fields of unpredictable widths, and if you are unwilling to truncate them, then you must resort to inspecting all of the output, storing it in the meantime, and then dynamically generating a format string which can accommodate the widest value in each column.

Regards,
Alister

OK, lets make it simpler. I've changed the code somewhat to amplify the specific problem.

I have two columns of data:
Think of the periods as actual spaces (the forum didnt allow a space to format the desired result)

volume1 disk1
............disk2
............disk3
volume2 disk4
............disk5
............disk6
volume3 disk3
............disk2
volume4 disk4
............disk8

Thats how I want them displayed. In reality they are displayed as such:

volume1 disk1
disk2
disk3
volume2 disk4
disk5
disk6
volume3 disk3
disk2
volume4 disk4
disk8

the code I'm using to format the output is below:

 
header="\n%-18s %-15s\n"
format="\n%-18s %-15s"
printf "${header}" "Volume" "Disk"
printf "${format}" "${volume}" "${diskvol}"

the data in ${volume} and ${diskvol} is being collected elsewhere and for this thread I'm only interested in how to make the 2nd, 3rd, 4th and so on values in the variable ${diskvol} respect the same formatting as the 1st value in said variable.

The actual output of the script is attached. it works as expected with the exception of the formatting. I'm stuck at how to force the printing of the 2nd and following values into the required column.

Help is much appreciated.

I never got the exact formatting I'd wanted but opted for a slightly different solution. Code follows:

#set column headers
header="\n\033[4m\033[1m%-18s %-35s %-25s %-8s %-10s\033[0m\033[0m"
format="\n%-18s %-35s %-25s %-8s %-10s"
printf "${header}" "Volume/Disk" "Block Device" "Mount Point" "Size" "Ownership"
for mntpnt in ${mountpoints}
do
 #displays BLOCKDEVICE - FS SIZE - MOUNT POINT - OWNER
 volume=$(/bin/df -hP $mntpnt | /bin/grep -v Filesystem | /bin/awk '{print $1}' | awk -F/ ' {print $6 }')
 diskvol=$(/sbin/vxprint -qtrg ${diskgroup} ${volume} | /bin/grep ^sd | /bin/grep -v "LOG" | /bin/awk '{ print $8 }' | /bin/sort -u |  sed -s 's/\s\+/\n/g' )
 blockdevice=$(/bin/df -hP $mntpnt | /bin/grep -v Filesystem | /bin/awk '{print $1 }')
 mntpnt=$(/bin/df -hP $mntpnt | /bin/grep -v Filesystem | /bin/awk '{print $6 }')
 fssize=$(/bin/df -hP $mntpnt | /bin/grep -v Filesystem | /bin/awk '{print $4 }')
 owner=$(/bin/ls -Ald ${mntpnt} | awk '{ print $3 ":" $4 }')
 #print the results
  printf "${format}" "${volume}" "${blockdevice}" "${mntpnt}" "${fssize}" "${owner}"
  for disk2vol  in ${diskvol};
  do
   printf "${format}" "   ${disk2vol}"
  done
done