1

folks. Currently I'm trying to parse lsblk output into array for further analysis in bash. The only problem I have is the empty columns that cause read -a to shift the fallowing values into incorrect place of the elements that are suppose to be empty. Here is the example:

# lsblk -rno MOUNTPOINT,FSTYPE,TYPE,DISC-GRAN 
/usr/portage ext2 loop 4K
  disk 512B
  part 512B
 ext2 part 512B
/ ext4 part 512B
/mnt/extended ext4 part 512B

The MOUNTPOINT and FSTYPE of second and third lines are empty as well as MOUNTPOINT of forth line, but 'traditional' read like this:

while read -r LINE; do
    IFS=' ' read -a ARRAY <<< $LINE
    echo "${ARRAY[0]};${ARRAY[1]};${ARRAY[2]};${ARRAY[3]}"
done < <(lsblk -rno MOUNTPOINT,FSTYPE,TYPE,DISC-GRAN)

Will produce an incorrect result with shifted columns an 0'th and 1'st element filled instead of 2nd and 3rd:

/usr/portage;ext2;loop;4K
disk;512B;;
part;512B;;
ext2;part;512B;
/;ext4;part;512B
/mnt/extended;ext4;part;512B

So, I wonder if there is some 'elegant' solution of this case or should I just do it the old way like I used to with a help of string.h in trusty C?

To be more clear, I need this values as array elements in for loop for analyses, not just to print this. Echoing is done just as an example of misbehavior.

2
  • This would probably be easier in awk, as you can check the line format more specifically. Commented Dec 27, 2019 at 22:21
  • 1
    tr ' ' ';' < <(lsblk -rno MOUNTPOINT,FSTYPE,TYPE,DISC-GRAN) Commented Dec 27, 2019 at 23:02

2 Answers 2

1

Why don't you specify -P option to lsblk to output in the form of key="value" pairs and read the output?

Then you can say something like:

while read -ra a; do
    for ((i=0; i<${#a[@]}; i++)); do
        a[i]=${a[i]#*=}     # extract rvalue
        a[i]=${a[i]//\"/}   # remove surrounding quotes
    done
    (IFS=';'; echo "${a[*]}")
done < <(lsblk -Pno MOUNTPOINT,FSTYPE,TYPE,DISC-GRAN)
Sign up to request clarification or add additional context in comments.

Comments

0

Use awk rather than bash for this. Use NF to assign the variables depending on how many fields are in the line.

awk -v 'OFS=;' 'NF == 4 { mountpoint = $1; fstype = $2; type = $3; gran = $4 }
                NF == 3 { mountpoint = ""; fstype = $1; type = $2; gran = $3 }
                NF == 2 { mountpoint = ""; fstype = ""; type = $1; gran = $2 }
                {print mountpoint, fstype, type, gran}' < <(lsblk -rno MOUNTPOINT,FSTYPE,TYPE,DISC-GRAN)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.