Команда вырезания не извлекает поля правильно в выровненных столбцах

У меня есть текстовый файл, в котором я должен вырезать поля 3,4,5 и 8:

219 432 4567 Harrison Joel M 4540 Accountant 09-12-1985 219 433 4587 Mitchell Barbara C 4541 Admin Asst 12-14-1995 219 433 3589 Olson Timothy H 4544 Supervisor 06-30-1983 219 433 4591 Moore Sarah H 4500 Dept Manager 08-01-1978 219 431 4527 Polk John S 4520 Accountant 09-22-1998 219 432 4567 Harrison Joel M 4540 Accountant 09-12-1985 219 432 1557 Harrison James M 4544 Supervisor 01-07-2000 

Поскольку по умолчанию разделителем является табуляция, команда для извлечения полей:

 cut -f 3,4,5,8 filename 

Дело в том, что результат совпадает с исходным содержимым файла. Что здесь происходит? Почему это не работает?

Не все эти промежутки между столбцами выглядят как вкладки, поэтому cut не сможет делать то, что вы хотите. Вместо этого я предлагаю использовать awk . Он более гибкий, чем cut при анализе столбцов данных, таких как то, что вы пытаетесь выполнить:

 $ awk '{print $3,$4,$5,$8}' data.txt 

пример

 $ awk '{print $3,$4,$5,$8}' data.txt 4567 Harrison Joel Accountant 4587 Mitchell Barbara Admin 3589 Olson Timothy Supervisor 4591 Moore Sarah Dept 4527 Polk John Accountant 4567 Harrison Joel Accountant 1557 Harrison James Supervisor 

Вы также можете разместить вывод с помощью команды column :

 $ awk '{print $3,$4,$5,$8}' data.txt |column -t 4567 Harrison Joel Accountant 4587 Mitchell Barbara Admin 3589 Olson Timothy Supervisor 4591 Moore Sarah Dept 4527 Polk John Accountant 4567 Harrison Joel Accountant 1557 Harrison James Supervisor 

Вы также можете делать все, используя только awk и printf :

 $ awk '{printf "%s\t%-20s\t%s\n",$3,$4" "$5,$8}' data.txt 4567 Harrison Joel Accountant 4587 Mitchell Barbara Admin 3589 Olson Timothy Supervisor 4591 Moore Sarah Dept 4527 Polk John Accountant 4567 Harrison Joel Accountant 1557 Harrison James Supervisor 

пересмотренный

Вышеуказанные методы выполняют задание OK, но они не обрабатывают ни одну из строк, где есть пробелы внутри значения для определенного столбца. Например, строка с «Dept Manager» получает нарезанный только Dept.

Если данные могут быть гарантированы как структуры, как показано, мы могли бы использовать cut но вместо разделения на разделителе мы могли бы просто отображать, используя фактические позиции символов.

пример

Это вырезает текст из файла data.txt и печатает все, что находится в положениях с 9 по 13 и с 14 по 35, и т. Д.

 $ cut -c 9-13,14-35,43-58 data.txt 4567 Harrison Joel Accountant 4587 Mitchell Barbara Admin Asst 3589 Olson Timothy Supervisor 4591 Moore Sarah Dept Manager 4527 Polk John Accountant 4567 Harrison Joel Accountant 1557 Harrison James Supervisor 

awk revisited

Awk также можно сделать, чтобы вытащить текст на основе его позиции, а не ограничителем. Это более подробный, хотя, но вот как, просто для полноты.

 $ awk '{ printf "%s\t%-20s\t%s\n",substr($0,9,5),substr($0,14,22),substr($0,43,16) }' data.txt 4567 Harrison Joel Accountant 4587 Mitchell Barbara Admin Asst 3589 Olson Timothy Supervisor 4591 Moore Sarah Dept Manager 4527 Polk John Accountant 4567 Harrison Joel Accountant 1557 Harrison James Supervisor 

awk FIELDWIDTHS

Если вы используете вариант GNU awk вы можете использовать переменную FIELDWIDTHS чтобы указать статический размер каждого поля. Это работает намного чище, чем метод substr , если у вас есть к нему доступ. Также вы можете эффективно склеивать поля, которые в противном случае анализировались бы как отдельные поля.

 $ awk 'BEGIN { FIELDWIDTHS="4 4 5 24 5 16 11" }{ print $3,$4,$5,$6 }' data.txt 4567 Harrison Joel M 4540 Accountant 4587 Mitchell Barbara C 4541 Admin Asst 3589 Olson Timothy H 4544 Supervisor 4591 Moore Sarah H 4500 Dept Manager 4527 Polk John S 4520 Accountant 4567 Harrison Joel M 4540 Accountant 1557 Harrison James M 4544 Supervisor 

Я предполагаю, что я не думаю, что это вкладки. Причина, по которой я не думаю, что это вкладки, заключается в том, что, когда я копирую файл и вручную группирую поля, то cut -f 3,4,5,8 filename похоже работает нормально. Возможно, вам лучше сделать cat filename | awk '{print $3, $4, $5, $8}' cat filename | awk '{print $3, $4, $5, $8}' если вы не хотите повторно заполнять поля и значения.