У меня есть текстовый файл, в котором мне нужно вырезать поля 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
Дело в том, что вывод такой же, как и исходное содержимое файла. Что здесь происходит? Почему это не работает?
решение1
Не все эти пробелы между столбцами выглядят как табуляции, поэтому 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
вырезать пересмотрено
Вышеуказанные методы работают нормально, но они не обрабатывают ни одну из строк, где есть пробелы в значении для определенного столбца. Например, строка с "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 снова посещен
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
Если вы используете вариант 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
решение2
Я предполагаю, что я не думаю, что это вкладки. Причина, по которой я не думаю, что это вкладки, заключается в том, что когда я копирую-вставляю файл и вручную табулирую поля, то, cut -f 3,4,5,8 filename
похоже, все работает нормально. Вам может быть лучше сделать это, cat filename | awk '{print $3, $4, $5, $8}'
если вы не хотите повторно табулировать поля и значения.