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

90

В оболочке я использую awk, когда мне нужен определенный столбец.

Это напечатает столбец 9, например:

... | awk '{print $9}'

Как мне сказать awk печатать все столбцы, включая столбец 9 и после него , а не только столбец 9?

Лазер
источник

Ответы:

83
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'
Амадан
источник
3
пара небольших уточнений:awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'
Гленн Джекман,
Спасибо @glenn, это действительно немного больше. В любом случае - однозначно согласен, что лучше использовать cutили perlдля этого. Используйте это, только если вы действительно настаиваете на его использовании awk.
Амадан
1
@SiegeX: он не добавляет байты NUL, он оставляет FS на месте между каждым пустым полем.
Приостановлено до дальнейшего уведомления.
1
Пожалуйста, посмотрите ответ @ Ascherer для элегантности.
3
@veryhungrymike: Элегантность - это хорошо, но я скорее буду прав. : p
Амадан
68

Когда вы хотите выполнить ряд полей, у awkвас действительно нет простого способа сделать это. cutВместо этого я бы порекомендовал :

cut -d' ' -f 9- ./infile

редактировать

Добавлен разделитель полей пробела, поскольку по умолчанию это вкладка. Спасибо Гленну за указание на это

SiegeX
источник
15
Одна вещь о cut заключается в том, что он использует определенный разделитель (по умолчанию табуляция), где awk использует «пробел». С вырезом две последовательные табуляции ограничивают пустое поле.
Гленн Джекман
1
Как отметил @glennjackman, разделителем awk является «пробел» (также любое количество). Таким образом, установка разделителя обрезки на один пробел тоже не будет соответствовать поведению. к сожалению, петля - лучшее, что можно сделать, так что это выглядит.
poncha
Этот не работает должным образом. Попробуйте команду find . | xargs ls -l | cut -d' ' -f 9-. Почему-то учитываются и двойные пробелы. Пример: lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_bрезультат./file_a 00:06 ./file_b
Марко Пашков
@MarcoPashkov, пожалуйста, поясните, что это не работает должным образом , особенно учитывая, что вы используете точно такой же код в своем конвейере.
Между
cut здесь не работает. Например, если вы введете «foo bar» (одиночный пробел) для одной строки и «foo ___ bar» (т.е. несколько пробелов, но SO слишком умен, чтобы показать это) для другой, cut обработает их по-другому.
UKMonkey
54
awk '{print substr($0, index($0,$9))}'

Изменить : обратите внимание, это не работает, если какое-либо поле до девятого содержит то же значение, что и девятое.

Ascherer
источник
3
это великолепно!
10
@veryhungrymike: ... и не работает, если какое-либо поле до девятого содержит то же значение, что и девятое.
Амадан
6
Вероятно, из-за классического предложения «надеюсь, в вашем файле нет этой проблемы». Не Ни в общей сложности нет-нет в с / ш техники в состояние: «мы не будем тратить время , включая ошибки проверки ввода например , отрицательные значения, потому что«мы надеемся , что пользователь будет умным достаточно , чтобы не попробовать их, сбой нашего инструмента ». ХАХАХА! Всегда приятно это слышать! (Мне нравится хорошее чувство юмора) Ну, поскольку идиоты действительно существуют, разработчик обязан сделать свои вещи защищенными от идиотов ! Вместо «надежды на хорошее в человеке». Скорее, такое отношение ожидается от философов, а не от инженеров программного обеспечения ... LOL
syntaxerror
3
Я не говорил не проверять ошибки, но если вы знаете, что не столкнетесь с проблемой, тогда это решение в порядке, как я уже сказал. Но спасибо за ненужный отрицательный голос @syntaxerror. Это решение будет работать для некоторых, поскольку (в настоящее время) 19 голосов за, но если это не так, не используйте его для своего решения. Есть много способов решить проблему OP.
Ascherer
1
Если вы используете awk в командной строке в своей повседневной работе, это определенно то решение, которое вам нужно. Разве это не очевидно? Проверка ошибок и т. Д. В этом случае не имеет особого значения, поскольку вы вводите его и можете уловить подобные вещи до того, как нажмете клавишу ввода (лично я не думаю, что awk в любом случае следует использовать для чего-то еще, поэтому мы у меня есть perl, python, tcl и около 100+ других, более качественных, быстрых, менее надоедливых языков сценариев!) Конечно, возможно, я слишком доверяю своим коллегам-разработчикам программного обеспечения, и им действительно нужна проверка ошибок даже в том, что они печатают на лету (??)
osirisgothra
11
sed -re 's,\s+, ,g' | cut -d ' ' -f 9-

Вместо того, чтобы иметь дело с пробелами переменной ширины, замените все пробелы одним пробелом. Затем используйте простой cutс интересующими полями.

Он не использует awk, поэтому не уместен, но казался подходящим с учетом других ответов / комментариев.

Какой-то дурак
источник
1
Пожалуйста, сделайте свой ответ более подробным, в противном случае опубликуйте его как комментарий к вопросу.
Альпер Туран
Это идеально подходит для ps faux | использования. Никогда не бойтесь признать инструмент XYZ не самым подходящим.
kevinf
10

Обычно perl заменяет awk / sed / grep et. др., и он гораздо более портативный (а также лучший перочинный нож).

perl -lane 'print "@F[8..$#F]"'

Timtowtdi, конечно, подает заявку.

бобого
источник
Вам нужно добавить параметр командной строки -lили добавить \nв оператор печати.
Гленн Джекман
@glenn jackman: Возможно. Не требуется, если является частью другого сообщения или присваивается переменной и т. Д. Что касается «лучше», Perl определенно выглядит лучше в малом. По общему признанию, может выглядеть очень неопрятно в целом.
bobbogo
Не поймите меня неправильно, мне нравится Perl. Я люблю awk такой, какая она есть.
Гленн Джекман
Мое встроенное устройство не поставляется с Perl, но у него есть awk.
Sepero
Голосование против, потому что был задан вопрос, как это сделать на awk, а не на perl, ruby, java, python, bash.
Том Харрисон,
3
awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Это обрезает то, что находится перед заданным номером поля, N, и печатает всю остальную часть строки, включая поле номер N и сохраняя исходный интервал (он не переформатируется). Не имеет значения, появляется ли строка поля также где-то еще в строке, что является проблемой с ответом Ашерера.

Определите функцию:

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

И используйте это так:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost   

Вывод поддерживает все, включая конечные пробелы. Для N = 0 он возвращает всю строку как есть, а для n> NF - пустую строку.

Роберт Вила
источник
Это хорошая идея. Это не совсем работает на текущем Mac с типичным gawk, потому что 0 долларов рухнет. Исправление состоит в том, чтобы в качестве первого шага установить для переменной значение $ 0, например: '{s = $ 0; ... print substr (s, index (s, m) +1}
joelparkerhenderson
1

Вот пример ls -lвывода:

-rwxr-----@ 1 ricky.john  1493847943   5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john  1493847943  27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john  1493847943  21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john  1493847943  10627144 Apr 16 14:09 03-Where to Get Help.mp4

Мое решение для печати всего поста $9-awk '{print substr($0, 61, 50)}'

рикидж
источник
0

Чтобы отобразить первые 3 поля и распечатать оставшиеся поля, вы можете использовать:

awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename

где $ 1 $ 2 $ 3 - первые 3 поля.

Раймонд С Борхес Хинк
источник
0
function print_fields(field_num1, field_num2){
    input_line = $0

    j = 1;
    for (i=field_num1; i <= field_num2; i++){
        $(j++) = $(i);

    }
    NF = field_num2 - field_num1 + 1;
    print $0

    $0 = input_line
}
msol01
источник
0

Использование cut вместо awk и решение проблем с определением, с какого столбца начинать, с помощью команды -c character cut.

Здесь я говорю, дайте мне все, кроме первых 49 символов вывода.

 ls -l /some/path/*/* | cut -c 50-

В /*/*/конце команды ls говорится, что покажите мне, что находится в подкаталогах.

Вы также можете вытащить определенные диапазоны символов ala (из вырезанной страницы руководства). Например, показать имена и время входа в систему пользователей, вошедших в систему в данный момент:

       who | cut -c 1-16,26-38
Джо
источник