RandomUser
RandomUser

Reputation: 4220

Bash simple string parse

Given this format:

DISKGROUP NAME    GB ALLOCATED         GB USED         GB FREE       USABLE GB PCT USED STATUS                          
-------------- --------------- --------------- --------------- --------------- -------- --------------------            
DISK_1             1,117.40          390.48          726.92          223.78    34.95 MOUNTED                         
DISK_2         1,117.40           65.97        1,051.43          386.04     5.90 MOUNTED   

With a single bash command how can I reliably get the value from GB FREE? The number of spaces between fields can very based on the field size, so I can't specify a static number of spaces with cut. Is there a way to use spaces as delimiter, but have the number of spaces be a variable size?

Thanks for any ideas

Upvotes: 1

Views: 443

Answers (2)

potong
potong

Reputation: 58568

This might work for you:

sed '1,2d;s/\(\S*\s*\)\{3\}\(\S*\).*/\2/' file

as above with headings:

sed '1,2c\ GB FREE\n--------'$'\n'';s/\(\S*\s*\)\{3\}\(\S*\).*/\2/' file

or for DISK_2 only:

sed '/^DISC_2/s/\(\S*\s*\)\{3\}\(\S*\).*/\2/p;d' file

as above with heading:

 sed '/^DISK_2/s/\(\S*\s*\)\{3\}\(\S*\).*/\2/;s/^/ GB FREE\n--------\n/p;d' file

Upvotes: 1

jaypal singh
jaypal singh

Reputation: 77185

You can use awk for this:

awk 'BEGIN {print "GB FREE\n--------"} NR>2{print $4}' INPUT_FILE

Explanation:

  1. We use awk's BEGIN statement to print the heading which is GB FREE and -------. This is because the heading in your input file has spaces in the titles. This can throw the awk script off.
  2. Second, we use awk's built-in variable NR which stores the line number. Since we don't want line 1 and 2 to be printed, we keep a condition of NR>2. This way awk will skip the first two lines and start printing from line 3.
  3. In awk by default, the delimiter or Field separator is spaces (one or more). Since your file has that we don't need to set the FS built-in variable. Each field separated by a space becomes a column and can be accessed using $ and column number. Since you want the GB FREE column which is 4, we do print $4.
  4. To keep more conditions, like printing only those lines where column 1 has DISK_2 we add another pattern statement. Using NR>2 && $1~/DISK_2/ ensures we don't print lines 1 and 2 and look for lines where column 1 has DISK_2 in them and print the column 4 of those lines.

Note: If you don't really care about the heading part, you can shorten this one-liner to the following (depending on your requirement):

awk 'NR>2{print $4}' INPUT_FILE

or

awk 'NR>2 && $1~/DISK_2/{print $4}' INPUT_FILE

Test:

[jaypal:~/Temp] cat file
DISKGROUP NAME    GB ALLOCATED         GB USED         GB FREE       USABLE GB PCT USED STATUS                          
-------------- --------------- --------------- --------------- --------------- -------- --------------------            
DISK_1             1,117.40          390.48          726.92          223.78    34.95 MOUNTED                         
DISK_2         1,117.40           65.97        1,051.43          386.04     5.90 MOUNTED   

[jaypal:~/Temp] awk 'BEGIN {print "GB FREE\n--------"} NR>2{print $4}' file
GB FREE
--------
726.92
1,051.43

To add filters as stated in the comments:

[jaypal:~/Temp] awk 'BEGIN {print "GB FREE\n--------"} NR>2 && $1~/DISK_2/{print $4}' file
GB FREE
--------
1,051.43

Upvotes: 7

Related Questions