Як надрукувати останні два стовпці за допомогою awk


106

Все, що я хочу, - це надруковані дві останні колонки.


6
Не зовсім впевнений, чому це 87 нагород, це, безумовно, можна покращити принаймні прикладом.
Арж

Можливо, тому, що питання надзвичайно просте за своєю суттю і легко зрозуміле без прикладу, що рідко, але в цьому випадку воно, здається, працює. Проблема тут не в нестачі інформації, але я думаю, що вона демонструє відсутність незалежних досліджень.
DryLabRebel

Це питання також є дублікатом цього питання.
DryLabRebel

Чи відповідає це на ваше запитання? Друк другого останнього стовпчика / поля в awk
DryLabRebel

Відповіді:


194

Ви можете використовувати змінну, NFяка встановлена ​​на загальну кількість полів у вхідному записі:

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

це передбачає, що у вас є щонайменше 2 поля.


1
Вам потрібна кома - оскільки ми сьогодні вибагливі: пробіл поєднує поля, кома відокремлює поля в операторі друку. Це об'єднає два поля
jim mcnamara

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)
jim mcnamara

1
@coaddict - Мабуть, ви не працювали з різними реалізаціями awk. Старі поведінки пробуджуються (можливо, помилково). Я не маю жодної перевірки на тест - напевно, на що ви посилаєтесь. Тож я точно не знаю, чому ваш коментар не став надійним. Linux awk з коробки, як правило, є gawk. Я тестую і відправлю назад. Тим часом спробуйте Soalris або HPUX або DGX або що завгодно, щоб побачити, що я маю на увазі під старим awk.
jim mcnamara

6
Ви, мабуть, натрапили на думку, що це працює, тому що ви намагалися echo 1 2 3 | awk .... $NF-1є ($NF) - 1в кожній awkреалізації.
Стефан Хазелас

У вихідному коді "One True Awk" є більше 40 конфліктів у yaccграматиці, що іронічно, враховуючи те, що A означає в awk. Різні версії awk розбирають речі по-різному? Великий сюрприз!
Каз

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

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.
jim mcnamara

+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

Я щойно ставлю гаук на Solaris 10 M4000: Отже, gawk є супротивником у випуску $ NF-1 проти $ (NF-1). Наступне питання, що говорить POSIX? за:

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

Немає напряму в той чи інший бік. Не добре. gawk передбачає віднімання, інші awks означають число поля або віднімання. хм.


1
Перші 2 рядки вашого вхідного файлу зразка не корисні, оскільки вони дають однаковий вихід із будь-якою поведінкою. Чи можете ви, будь ласка, підтвердити, що Solaris awk насправді НЕ веде себе так, як гаук?
mklement0

Що стосується вашого посилання на специфікацію awk: Анекдотичний аргумент використання $(NF-1)полягає в тому, що обидва приклади обчислення індексу поля в специфікації використовують таку форму: $(NF-1)і $(NF+2). Тоді є розділ "Вирази у курсі", в якому вказано $expr, що має [набагато] перевагу вище expr - expr. Оскільки NFце само вираження, $NF-1слід оцінювати ($NF)-1. Навіть якщо, зрештою, там дійсно є дивовижні реалізації, які оцінюють $NF-1як $(NF-1), уроки, засвоєні тут, - це те, що використання $(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.