Вывести второй последний столбец / поле в awk


165

Я хочу напечатать второй последний столбец или поле в awk. Количество полей является переменным. Я знаю, что я должен быть в состоянии использовать, $NFно не уверен, как это можно использовать.

И это, похоже, не работает

awk ' { print ( $NF-- )  } '

10
NFпоследний индекс поля, $NFэто значение последнего поля
Гленн Джекман

это имеет смысл сейчас. вот почему доллар за скобками работает, я полагаю
Брайан Дж.

Ответы:


280
awk '{print $(NF-1)}'

Должно сработать


2
Это не работает для меня. Я получаю "title: 5: команда не найдена: NF-1" в awk 3.1.8 под Ubuntu.
Гург

3
Я хотел бы избежать декремента до / после, чтобы убедиться, что вы не измените значение $ NF
Грегори Патмор

Это сломается, если вы попытаетесь получить третье последнее поле, напримерawk -F '.' '{print $(NF-2)}'
gies0r

3
@Gurgeh: Это происходит потому, что $(..)вызывает команду в подоболочке в зависимости от того, какую оболочку вы используете. Вы можете обойти это, используя $ (NF-1)вместо $(NF-1).
августа

21

Небольшое дополнение к принятому ответу Криса Каннона: печатать, только если на самом деле есть второй последний столбец.

(
echo       | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1     | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2   | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2 3 | awk 'NF && NF-1 { print ( $(NF-1) ) }'
)

15

Это самое простое:

 awk '{print $--NF}' 

Причина, по которой оригинал $NF--не сработал, заключается в том, что выражение вычисляется перед декрементом, тогда как декремент моего префикса выполняется перед вычислением.


Как мнемоника, это поведение аналогично C / Java и т. Д. int x = ++i int x = i++, Префикс означает сначала увеличение; Постфикс означает увеличение позже (назначение сначала).
Выходные


4

Вы были недалеко от результата! Это делает это:

awk '{NF--; print $NF}' file

Это уменьшает количество полей в одном, так что $NFсодержит первое предпоследнее.

Тест

Давайте сгенерируем несколько чисел и напечатаем их по группам из 5:

$ seq 12 | xargs -n5
1 2 3 4 5
6 7 8 9 10
11 12

Давайте напечатаем предпоследний на каждой строке:

$ seq 12 | xargs -n5 | awk '{NF--; print $NF}'
4
9
11

3

Perl-решение, похожее на awk-решение Криса Каннона:

perl -lane 'print $F[$#F-1]' file

Эти параметры командной строки используются:

  • n цикл вокруг каждой строки входного файла, не печатать автоматически каждую строку

  • l удаляет символы новой строки перед обработкой и добавляет их обратно после

  • aРежим автоматического разделения - разбить входные строки в @Fмассив. По умолчанию расщепление по пробелам

  • e выполнить код Perl

@FМассив AutoSplit начинается с индекса [0] в то время как поля AWK начать с $ 1.
$#Fэто количество элементов в@F


1
или используйте отрицательную индексацию, уже предоставленную perl ...$F[-2]
Sundeep

2

Вы пытались начать справа налево с помощью команды rev? В этом случае вам просто нужно напечатать 2-й столбец:

seq 12 | xargs -n5 | rev | awk '{ print $2}' | rev
4
9
11

1

Сначала уменьшает значение, а затем печатает его -

awk ' { print $(--NF)}' file

ИЛИ

rev file|cut -d ' ' -f2|rev

0

Если у вас много столбцов и вы хотите напечатать все, кроме трех, в последнем случае, то это может помочь

awk '{ $NF="";$(NF-1)="";$(NF-2)="" ; print $0 }'

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.