Как распечатать последние два столбца с помощью awk


106

Все, что мне нужно, это напечатать последние два столбца.


6
Не совсем уверен, почему у него 87 голосов, это, безусловно, можно улучшить, по крайней мере, на примере.
Arj

Вероятно, потому что вопрос чрезвычайно прост по своей природе и его легко понять без примера, что бывает редко, но в данном случае он работает. Я думаю, проблема здесь не в отсутствии информации, а в том, что это свидетельствует об отсутствии независимых исследований.
DryLabRebel

Этот вопрос также является дубликатом этого вопроса.
DryLabRebel

Ответы:


194

Вы можете использовать переменную, NFкоторая установлена ​​на общее количество полей во входной записи:

awk '{print $(NF-1),"\t",$NF}' file

это предполагает, что у вас есть как минимум 2 поля.


1
Вам нужна запятая - поскольку мы сегодня разборчивы: пробел объединяет поля, запятая разделяет поля в операторе печати. Это объединит два поля
Джим Макнамара

18
Теперь вы печатаете «поле-OFS-вкладка-OFS-поле». Это должно быть awk '{print $(NF-1) "\t" $NF}' fileили awk '{print $(NF-1), $NF}' fileили awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
Приостановлено до дальнейшего уведомления.

Чтобы добавить к предыдущему комментарию, проблема с использованием '{print $x,"\t",$y}'заключается в том, что awk интерпретирует каждую переменную, разделенную запятыми, как свое собственное поле, поэтому результат будет фактически field1<space><tab><space>field2(потому что он будет использовать разделитель пробелов по умолчанию), в отличие от того, field1<tab>field2что, вероятно, вы ожидаете. использование разделителя выходных полей (OFS) - это почти всегда то, что вам нужно.
DryLabRebel

13
awk '{print $NF-1, $NF}'  inputfile

Примечание: это работает, только если существует как минимум два столбца. На записях с одним столбцом вы получите ложный"-1 column1"


3
Попробуй и увидишь. Работает Solaris 9 awk & nawk. Альтернатива - $ (NF-1)
Джим Макнамара

1
@coaddict - я предполагаю, что вы не работали с разными реализациями awk. Было перенесено (возможно, ошибочно) поведение старых awks. У меня нет глаз, чтобы протестировать - возможно, вы на это ссылаетесь. Так что я точно не знаю, почему ваш комментарий поступил неожиданно. Linux awk из коробки обычно gawk. Я протестирую и отправлю обратно. А пока попробуйте Soalris, HPUX, DGX или что-то еще, чтобы понять, что я имею в виду под старым awk.
Джим Макнамара

6
Вероятно, вас обманом заставили думать, что это сработало, потому что вы пытались echo 1 2 3 | awk .... $NF-1есть ($NF) - 1в каждой awkреализации.
Стефан Шазелас

Исходный код "One True Awk" имеет более 40 конфликтов в yaccграмматике, что является иронией, учитывая, что означает A в awk. Разные версии awk по-разному разбирают вещи? Большой сюрприз!
Kaz

1
@THESorcerer, попробуйте с echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- или любым другим вводом, в котором второе последнее поле не на единицу меньше последнего поля.
Гленн Джекман

6

@jim mcnamara: попробуйте использовать круглые скобки вокруг NF, т.е. $(NF-1)и $(NF)вместо $NF-1и $NF(работает в Mac OS X 10.6.8 для FreeBSD awkи gawk).

echo '
1 2
2 3
one
one two three
' | gawk '{if (NF >= 2) print $(NF-1), $(NF);}'

# output:
# 1 2
# 2 3
# two three

Мы уже рассматривали () ранее. Я думал, мы обсуждали, откуда взялось исходное старое поведение awk.
Джим Макнамара

+1 за ответ с явным $(NF-1)- что, по крайней мере, более переносимо, чем $NF-1; это определенно менее двусмысленно. $(NF)это излишество - просто $NFподойдет. Защита от строк с менее чем 2 столбцами также имеет смысл, так как в строках с одним столбцом вы получите значение первого столбца дважды , а с нулевыми столбцами, то есть пустыми, команда awk полностью завершится с ошибкой из-за попытки для доступа к полю с индексом -1.
mklement0

1

использование gawk демонстрирует проблему:

 gawk '{ print $NF-1, $NF}' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three

Я только что поставил gawk на Solaris 10 M4000: Итак, gawk - это главная проблема в проблеме $ NF-1 против $ (NF-1). Следующий вопрос: что говорит POSIX? за:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

В том или ином направлении нет направления. Не хорошо. gawk подразумевает вычитание, другие awks подразумевают номер поля или вычитание. хм.


1
Первые две строки вашего примера входного файла бесполезны, поскольку они производят одинаковый вывод при любом поведении. Не могли бы вы подтвердить, что Solaris awk действительно НЕ ведет себя как gawk в этом случае?
mklement0

Что касается вашей ссылки на спецификацию awk: анекдотический аргумент в пользу использования $(NF-1)заключается в том, что оба примера вычисления индекса поля в спецификации используют эту форму: $(NF-1)и $(NF+2). Затем есть раздел «Выражения в awk», в котором указано, $exprчто они имеют [намного] более высокий приоритет, чем expr - expr. Поскольку NFсамо выражение, $NF-1должно оцениваться как ($NF)-1. В конце концов, даже если IF действительно существуют реализации awk, которые оценивают $NF-1as $(NF-1), урок, извлеченный здесь, состоит в том, что using $(NF-1)- это безопасный и переносимый выбор.
mklement0

0

попробуйте с этим

$ cat /tmp/topfs.txt
/dev/sda2      xfs        32G   10G   22G  32% /

awk print last column
$ cat /tmp/topfs.txt | awk '{print $NF}'

awk print before last column
$ cat /tmp/topfs.txt | awk '{print $(NF-1)}'
32%

awk - print last two columns
$ cat /tmp/topfs.txt | awk '{print $(NF-1), $NF}'
32% /

0

Попробуйте это, чтобы учесть все возможные сценарии:

awk '{print $(NF-1)"\t"$NF}'  file

или

awk 'BEGIN{OFS="\t"}' file

или

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.