Bash простой анализ строки - PullRequest
1 голос
/ 06 января 2012

Учитывая этот формат:

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   

С помощью одной команды bash, как я могу надежно получить значение из GB FREE? Количество пробелов между полями может сильно зависеть от размера поля, поэтому я не могу указать статическое количество пробелов с помощью cut. Есть ли способ использовать пробелы в качестве разделителя, но есть ли количество пробелов переменного размера?

Спасибо за любые идеи

Ответы [ 2 ]

7 голосов
/ 06 января 2012

Вы можете использовать awk для этого:

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

Пояснение:

  1. Мы используем оператор awk's BEGIN, чтобы напечатать заголовок, который GB FREE and -------. Это потому, что заголовок в вашем входном файле имеет пробелы в заголовках. Это может сбить сценарий awk.
  2. Во-вторых, мы используем awk's встроенную переменную NR, в которой хранится номер строки. Поскольку мы не хотим, чтобы строки 1 и 2 печатались, мы сохраняем условие NR>2. Таким образом, awk пропустит первые две строки и начнет печатать со строки 3.
  3. В awk по умолчанию в качестве разделителя или разделителя полей используется пробел (один или несколько). Так как ваш файл имеет это, нам не нужно устанавливать встроенную переменную FS. Каждое поле, разделенное пробелом, становится столбцом и может быть доступно с помощью $ и column number. Поскольку вам нужен столбец GB FREE, равный 4, мы делаем print $4.
  4. Чтобы сохранить больше условий, например, печатать только те строки, где column 1 имеет DISK_2, мы добавляем еще один оператор шаблона. Использование NR>2 && $1~/DISK_2/ гарантирует, что мы не печатаем строки 1 и 2, ищем строки, в которых column 1 содержит DISK_2, и печатаем column 4 этих строк.

Примечание: Если вы не очень заботитесь о заголовочной части, вы можете сократить эту однострочную до следующего (в зависимости от ваших требований):

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

или

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

Тест:

[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

Чтобы добавить фильтры, как указано в комментариях:

[jaypal:~/Temp] awk 'BEGIN {print "GB FREE\n--------"} NR>2 && $1~/DISK_2/{print $4}' file
GB FREE
--------
1,051.43
1 голос
/ 07 января 2012

Это может работать для вас:

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

как указано выше с заголовками:

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

или только DISK_2:

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

как указано выше с заголовком:

 sed '/^DISK_2/s/\(\S*\s*\)\{3\}\(\S*\).*/\2/;s/^/ GB FREE\n--------\n/p;d' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...