I would like to parse the column elements of the output from the command lsscsi.

Here is a sample output,

# lsscsi

[0:0:0:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sda
[0:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdb
[1:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdc

Example if I want column 2, my output should be,

disk
disk
disk

If cloumn 7,

/dev/sda
/dev/sdb
/dev/sdc

Thanks

有帮助吗?

解决方案

Use awk like this:

awk -v col=7 '{print $col}' file

Or to print 2 colimns:

awk -v col1=2 -v col2=7 '{print $col1, $col2}' file

OR to make it print multiple columns:

awk -v col='2:7' '{split (col, a, ":"); for (i in a) printf "%s%s", $a[i], OFS; print ""}' file

其他提示

With bash you can use 'read -a', this reads a line from standard input, splits using IFS field separator which has space by default and populates array variable which can be referenced as ${array[n]} (zero based).

while read -a arr; do
    echo "${arr[1]}"
    echo "${arr[6]}"
done

Unfortunately lsscsi does not provide consistent parseable output nor the chance to change the field separator as far as I see. With two different harddisks on the same system the column for the device is differing by one! The following code sniplet should give you an idea about what I mean and how I worked around it... at least to get the device which is at the end of the line. To get the product name and the product revision correctly, it could also be an idea to call each device with lssci -c a:b:c:d and then parse this output.

lsscsi > /tmp/tmp$$.out
while read line
do
    echo $line
    echo 012345678901234567890123456789012345678901234567890123456789
    echo 0.........1.........2.........3.........4.........5.........
    ID=$(echo $line | cut -c2)
    TYPE=$(echo $line | cut -c16-18)
    PRODUCT=$(echo $line | sed -n 's/.\{18\}\(.*\) *\/dev\/.*/\1/p')
    DEVICE=$(echo $line | sed -n 's/.\{18\}.*\/dev\/\(.*\)/\1/p')
    echo $ID-$TYPE-$DEVICE-$PRODUCT
done

Another easy way to do it without awk:

lsscsi | tr -s ' ' | cut -d' ' -f7

The last flag specifies the column.

Simple examples:
(Each example is independent.)

Select the column 2:

echo -e "[0:0:0:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sda \
  \n[0:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdb \
  \n[1:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdc" \
  | awk '{print $2}'

Select the column 7:

echo -e "[0:0:0:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sda \
  \n[0:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdb \
  \n[1:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdc" \
  | awk '{print $7}'

Select the column 2 & 7:

echo -e "[0:0:0:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sda \
  \n[0:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdb \
  \n[1:0:1:0]   disk   ATA   VBOX HARDDISK   1.0   /dev/sdc" \
  | awk '{print $2, $7}'

Results:

enter image description here

You may want to use the separation in columns with lsscsi : Use perl to insert tab and trim the fields.

lsscsi -g \
| perl -ne 'foreach$c(qw (64 53 47 30 21 13)){
              substr$_,$c,0,"\t"
            };
            s/ *([\t\n])/\1/g;  # trim the fields
            print'

Or one liner :

 lsscsi -g|perl -ne 'foreach$c(qw(64 53 47 30 21 13)){substr$_,$c,0,"\t"};s/ *([\t\n])/\1/g;print'
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top