Не совсем уверен, почему у него 87 голосов, это, безусловно, можно улучшить, по крайней мере, на примере.
Arj
Вероятно, потому что вопрос чрезвычайно прост по своей природе и его легко понять без примера, что бывает редко, но в данном случае он работает. Я думаю, проблема здесь не в отсутствии информации, а в том, что это свидетельствует об отсутствии независимых исследований.
DryLabRebel
Этот вопрос также является дубликатом этого вопроса.
Вам нужна запятая - поскольку мы сегодня разборчивы: пробел объединяет поля, запятая разделяет поля в операторе печати. Это объединит два поля
Джим Макнамара
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"
Попробуй и увидишь. Работает 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
1223-1 one
-1 three
# cat filename1223
one
one two three
Я только что поставил gawk на Solaris 10 M4000: Итак, gawk - это главная проблема в проблеме $ NF-1 против $ (NF-1). Следующий вопрос: что говорит POSIX? за:
Первые две строки вашего примера входного файла бесполезны, поскольку они производят одинаковый вывод при любом поведении. Не могли бы вы подтвердить, что 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)- это безопасный и переносимый выбор.
Ответы:
Вы можете использовать переменную,
NF
которая установлена на общее количество полей во входной записи:это предполагает, что у вас есть как минимум 2 поля.
источник
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) - это почти всегда то, что вам нужно.Примечание: это работает, только если существует как минимум два столбца. На записях с одним столбцом вы получите ложный
"-1 column1"
источник
echo 1 2 3 | awk ...
.$NF-1
есть($NF) - 1
в каждойawk
реализации.yacc
грамматике, что является иронией, учитывая, что означает A в awk. Разные версии awk по-разному разбирают вещи? Большой сюрприз!echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'
- или любым другим вводом, в котором второе последнее поле не на единицу меньше последнего поля.@jim mcnamara: попробуйте использовать круглые скобки вокруг
NF
, т.е.$(NF-1)
и$(NF)
вместо$NF-1
и$NF
(работает в Mac OS X 10.6.8 для FreeBSDawk
иgawk
).источник
$(NF-1)
- что, по крайней мере, более переносимо, чем$NF-1
; это определенно менее двусмысленно.$(NF)
это излишество - просто$NF
подойдет. Защита от строк с менее чем 2 столбцами также имеет смысл, так как в строках с одним столбцом вы получите значение первого столбца дважды , а с нулевыми столбцами, то есть пустыми, команда awk полностью завершится с ошибкой из-за попытки для доступа к полю с индексом -1.использование gawk демонстрирует проблему:
Я только что поставил gawk на Solaris 10 M4000: Итак, gawk - это главная проблема в проблеме $ NF-1 против $ (NF-1). Следующий вопрос: что говорит POSIX? за:
В том или ином направлении нет направления. Не хорошо. gawk подразумевает вычитание, другие awks подразумевают номер поля или вычитание. хм.
источник
$(NF-1)
заключается в том, что оба примера вычисления индекса поля в спецификации используют эту форму:$(NF-1)
и$(NF+2)
. Затем есть раздел «Выражения в awk», в котором указано,$expr
что они имеют [намного] более высокий приоритет, чемexpr - expr
. ПосколькуNF
само выражение,$NF-1
должно оцениваться как($NF)-1
. В конце концов, даже если IF действительно существуют реализации awk, которые оценивают$NF-1
as$(NF-1)
, урок, извлеченный здесь, состоит в том, что using$(NF-1)
- это безопасный и переносимый выбор.попробуйте с этим
источник
Попробуйте это, чтобы учесть все возможные сценарии:
или
или
источник