Як надрукувати третій стовпець до останнього стовпця?


121

Я намагаюся видалити перші два стовпці (з яких мене не цікавлять) з файлу журналу DbgView. Я не можу знайти приклад, який друкує з стовпця 3 і далі до кінця рядка. Зауважте, що кожен рядок має змінну кількість стовпців.


Відповіді:


108

... або більш просте рішення: cut -f 3- INPUTFILE просто додайте правильний роздільник (-d), і ви отримали такий же ефект.


9
Зауважте, що це працює лише в тому випадку, якщо роздільник є однаковим між усіма стовпцями ... Наприклад, ви не можете використовувати вирізати з роздільником, як \ d +. (Те, що я знаю.)
Зак Вілі

72
Коли питання має назву awk, недоцільно приймати відповідь, крім awk. Що робити, якщо людям це потрібно для сценаріїв awk? Ця відповідь мала бути лише коментарем.
сяз

24
@SyaZ: Зазвичай я погоджуюся, але, маючи кількість "безплатних див" на цій дошці, я вважав, що потрібно показати альтернативний спосіб виконання завдання. Чи не будете ви вдячні, якби хтось показав вам простіший і швидший спосіб виконати те саме завдання? Можливо, афіша подумала, що awk - це єдиний спосіб зробити це через численні відповіді на "невірні, але, безумовно, незрозумілі" відповіді на інші запитання?
Марцін

12
Ось до чого йде коментар. Прийміть найкращу відповідь на відповідь та надайте кращі пропозиції, що не стосуються коментарів. Якщо люди почнуть публікувати відповіді, які не відповідають точно на запитання, це буде дратувати при пошуку (в моєму випадку).
сяз

12
Не тільки роздільники повинні бути однаковими між усіма стовпцями, але мають бути ТОЧНО ОДНИМ роздільником символів між стовпцями. Тож якщо ви маєте справу з програмами, які вирівнюють їх вихід з роздільниками, краще використовувати awk.
sknaumov

112
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' бути більш компактним. :)
користувач172818

1
Спасибі, lh3. Я просто копіював і вставляв посібник з gawk. :)
Джонатан Фейнберг

23
це не вдається з декількома рядками, кожен стовпець відзначається як новий рядок, коли надруковано
iwth

13
Щоб вирішити питання про розщеплений вихід, я пропоную таке рішення: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfне буде друкувати print ""
таблицю

1
Або: echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', що дає: 3 4 5 6 7 8 9 10.
x-yuri

106
awk '{ print substr($0, index($0,$3)) }'

тут знайдено рішення:
http://www.linuxquestions.org/questions/linux-newbie-8/awk-print-field-to-end-and-character-count-179078/


23
Я запізнююсь на це, але це не спрацює для записів, у яких перше або друге поле дорівнює третьому (наприклад, 3 2 3 4 5)
aleph_null

також можливий друк внутрішнього діапазону: `` # від $ 3 (включено) до $ 6 (виключено); відлуння "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {print substr ($ 0, індекс ($ 0, $ 3), довжина ($ 0) -index ($ 0, $ 6) -1)}'; # дає 3,4,5```
сплайсан

34

Відповідь Джонатана Файнберга друкує кожне поле окремим рядком. Ви можете скористатися printfдля відновлення запису для виведення на одному рядку, але ви також можете просто перемістити поля вліво.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

1
Пам’ятайте, що це працює лише для Gnu awk, декрементація NFзаборонена POSIX.
kvantour

1
@kvantour: Це працює в gawk, mawk, MacOS awk (nawk?). Здається, POSIX мовчить про те, чи NFможна зменшити їх.
Призупинено до подальшого повідомлення.

Це один із цих кумедних темних куточків awk .
kvantour

19
awk '{$1=$2=$3=""}1' file

Примітка: цей метод залишить «пробіли» в 1,2,3 полях, але це не проблема, якщо ви просто хочете подивитися на вихід.


Прослідкуйте цю команду за допомогою "| sed s / ^ \ * // | стовпчик -t`, щоб зняти провідні пробіли та вирівняти решту стовпців
MSpreij

Що означає останнє 1? за яким ключовим словом слід шукати awk?
Ітачі

@Itachi див. Приклад 1 з catonmat.net/blog/awk-one-liners-explained-part-one
kvantour

1
@Nathan ви вирішите це питання як{$1=$2=$3="";$0=$0;$1=$1}1
kvantour

11

Якщо ви хочете надрукувати стовпці після 3-го, наприклад, у тому ж рядку, ви можете використовувати:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

Наприклад:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

Він надрукує:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

Як ми бачимо, розкладник навіть з простором відображається у правильному рядку.


Швидкий і гладкий. Дякую;)
9nz9

Це чудово, за винятком випадків, коли у мене проблема з виключенням $ NF. Коли я встановлюю умову (<= NF), я отримую останнє поле, але перший символ першого поля відсікається. Я щось розумію з точки зору функціональності?
Кен Інграм

Схоже, моя проблема полягає в тому, що ^ M застряг в кінці останнього стовпця. Не бачите, як її видалити.
Кен Інграм

8

Як щодо наступного рядка:

awk '{$ 1 = $ 2 = $ 3 = ""; print} 'файл

На основі пропозиції @ ghostdog74. Моя повинна поводитись краще, коли ви фільтруєте лінії, тобто:

awk '/ ^ exim4-config / {$ 1 = ""; print} 'файл

Короткий і простий. Можна також передавати та додавати sed 's/\s\+//g'наприкінці команди для обрізки провідних просторів
jumping_monkey

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

Це розбиває те, що знаходиться перед заданими полями nr., N, і друкує всі інші рядки, включаючи поле nr.N та підтримуючи початковий інтервал (він не переформатується). Немає значення, якщо рядок поля з’являється ще десь у рядку, що є проблемою у відповіді дайса.

Визначте функцію:

fromField () { 
awk -v m="\x0a" -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' є роздільником записів, тому у вас немає цього нового рядка. Якщо ви хочете використовувати його з іншими роздільниками записів, тоді використовуйте:

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

наприклад. Добре працює з майже всіма файлами, доки вони не використовують шістнадцятковий символ char. 1 всередині рядків.


4

Наступна команда awk друкує останні N полів кожного рядка, а в кінці рядка друкує новий символ рядка:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

Нижче знайдіть приклад, який містить список вмісту каталогу / usr / bin, а потім містить останні 3 рядки, а потім друкує останні 4 стовпчики кожного рядка за допомогою awk:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

4
awk '{a=match($0, $3); print substr($0,a)}'

Спочатку ви знаходите позицію початку третього стовпця. За допомогою substr ви надрукуєте весь рядок ($ 0), починаючи з позиції (у цьому випадку a) до кінця рядка.


3

Ну, ви можете легко досягти того ж ефекту, використовуючи регулярний вираз. Якщо припустити, що роздільник є пробілом, це виглядатиме так:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
Я б уникнув регулярного вираження. Напевно, повільніше і легше випадково зіпсуватись.
Каскабель

1
Це скорочується так: awk '{ sub(/([^ ]+ +){2}/, ""); print }'що знімає візерунок у два рази.
Ерік


2

Розчин Perl:

perl -lane 'splice @F,0,2; print join " ",@F' file

Ці параметри командного рядка використовуються:

  • -n циклічно навколо кожного рядка вхідного файлу, не друкуйте кожен рядок автоматично

  • -l видаляє нові рядки перед обробкою та додає їх згодом

  • -aрежим автоспліт - розділити вхідні лінії в масив @F. За замовчуванням розділяється на пробіл

  • -e виконати код Perl

splice @F,0,2 чисто видаляє стовпці 0 і 1 з масиву @F

join " ",@F приєднується до елементів масиву @F, використовуючи пробіл між ними

Якщо ваш вхідний файл обмежений комами, а не з пробілом, використовуйте -F, -lane


Рішення Python:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file


1

Тут трохи пізно, але ніщо з вищезазначеного, здавалося, не спрацювало. Спробуйте це, використовуючи printf, вставляючи пробіли між ними. Я вирішив не мати нової лінії в кінці.

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'

1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

друкує записи, починаючи з 4-го поля до останнього поля в тому ж порядку, який вони були у вихідному файлі


вибачте, це була не зовсім правильна відповідь. це занадто конкретно, але я не знаю, як його видалити
Массімо


0

Якщо мова йде лише про ігнорування перших двох полів, і якщо ви не хочете пробілу під час маскування цих полів (як це зроблено у деяких відповідях вище):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

Перші два стовпці очищаються, sedвидаляються провідні пробіли.


-2

У AWK стовпці називаються полями, отже, NF є ключем

всі рядки:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

лише перший рядок:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.