Bagaimana cara mencetak kolom ketiga ke kolom terakhir?


121

Saya mencoba untuk menghapus dua kolom pertama (yang saya tidak tertarik) dari file log DbgView. Saya tidak bisa menemukan contoh yang dicetak dari kolom 3 dan seterusnya sampai akhir baris. Perhatikan bahwa setiap baris memiliki jumlah kolom yang bervariasi.


Jawaban:


108

... atau solusi yang lebih sederhana: cut -f 3- INPUTFILE cukup tambahkan pembatas yang benar (-d) dan Anda mendapatkan efek yang sama.


9
Perhatikan bahwa ini hanya berfungsi jika pembatasnya persis sama di antara semua kolom ... Misalnya, Anda tidak dapat menggunakan cut dengan pembatas seperti \ d +. (Yang saya tahu.)
Zach Wily

72
Ketika pertanyaan berjudul awk, tidak pantas menerima jawaban selain awk. Bagaimana jika orang membutuhkannya untuk skrip awk? Jawaban ini seharusnya hanya menjadi komentar.
syaz

24
@SyaZ: Biasanya saya setuju, tetapi dengan jumlah 'serampangan' yang terjadi di papan ini, saya pikir perlu menunjukkan cara alternatif untuk melakukan tugas. Tidakkah Anda akan bersyukur jika seseorang menunjukkan kepada Anda cara yang lebih sederhana dan lebih cepat untuk melakukan tugas yang sama? Mungkin poster menganggap awk adalah satu-satunya cara untuk melakukan ini karena banyaknya jawaban 'tidak salah, tapi pasti dapat ditingkatkan pada' untuk pertanyaan lain?
Marcin

12
Untuk itulah komentar itu. Terima jawaban awk terbaik dan berikan saran non-awk yang lebih baik pada komentar. Jika orang mulai memposting jawaban yang tidak benar-benar menjawab pertanyaan, itu akan mengganggu saat mencari (dalam kasus saya).
syaz

12
Tidak hanya pembatas harus sama di antara semua kolom, tetapi harus ada PERSIS SATU karakter pembatas antar kolom. Jadi jika Anda berurusan dengan program yang menyelaraskan keluarannya dengan pembatas, lebih baik menggunakan awk.
sknaumov

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

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' lebih ringkas. :)
user172818

1
Terima kasih, lh3. Saya baru saja menyalin dan menempel untuk manual gawk. :)
Jonathan Feinberg

23
ini gagal dengan beberapa baris, setiap kolom ditransformasikan sebagai baris baru saat dicetak iwth print
meso_2600

13
Untuk mengatasi masalah keluaran yang terpecah, saya mengusulkan solusi ini: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printftidak akan mencetak karakter baris baru sementara print ""akan menambahkan baris baru setelah bidang lain telah dicetak)
lauhub

1
Atau: echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', yang memberikan: 3 4 5 6 7 8 9 10.
x-yuri

106

23
Saya agak terlambat untuk ini, tetapi ini tidak akan berfungsi untuk rekaman di mana bidang pertama atau kedua sama dengan yang ketiga (misalnya, 3 2 3 4 5)
aleph_null

mencetak kisaran internal juga dimungkinkan: `` # dari $ 3 (termasuk) hingga $ 6 (tidak termasuk); echo "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {print substr ($ 0, index ($ 0, $ 3), length ($ 0) -index ($ 0, $ 6) -1)}'; # memberikan 3,4,5```
splaisan

34

Jawaban Jonathan Feinberg mencetak setiap bidang pada baris terpisah. Anda dapat menggunakan printfuntuk membangun kembali rekaman untuk keluaran pada baris yang sama, tetapi Anda juga dapat memindahkan bidang dengan lompatan ke kiri.

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

1
Ketahuilah, bahwa ini hanya berfungsi untuk Gnu awk, pengurangan NFtidak diperbolehkan oleh POSIX.
kvantour

1
@kvantour: Ia bekerja di gawk, mawk, MacOS awk (nawk?). POSIX tampaknya tidak bersuara tentang apakah NFdapat dikurangi.
Dijeda sampai pemberitahuan lebih lanjut.

Ini adalah salah satu sudut gelap yang lucu dari awk .
kvantour

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

NB: metode ini akan membiarkan "kosong" di 1,2,3 bidang tetapi tidak menjadi masalah jika Anda hanya ingin melihat keluaran.


Lacak perintah itu dengan `| sed s / ^ \ * // | kolom -t` untuk menghapus spasi di depan dan menyejajarkan kolom yang tersisa
MSpreij

Apa arti terakhir 1? dengan kata kunci apa saya harus mencari awk?
Itachi


1
@Nathan Anda memecahkan masalah ini sebagai{$1=$2=$3="";$0=$0;$1=$1}1
kvantour

11

Jika Anda ingin mencetak kolom setelah tanggal 3 misalnya di baris yang sama, Anda dapat menggunakan:

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

Sebagai contoh:

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

Ini akan mencetak:

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

Seperti yang bisa kita lihat, slip gaji bahkan dengan spasi, ditampilkan di baris yang benar.


Cepat dan rapi. Terima kasih;)
9nz9

Ini luar biasa, kecuali saya punya masalah dengan $ NF dikecualikan. Ketika saya mengatur kondisi (<= NF) saya mendapatkan bidang terakhir tetapi karakter pertama bidang pertama terpotong. Apakah saya salah paham dalam hal fungsionalitas?
Ken Ingram

Sepertinya masalah saya adalah ^ M tertahan di akhir kolom terakhir. Tidak melihat cara menghapusnya.
Ken Ingram

8

Bagaimana dengan baris berikut:

awk '{$ 1 = $ 2 = $ 3 = ""; print} '

Berdasarkan saran @ ghostdog74. Milik saya harus berperilaku lebih baik saat Anda memfilter garis, yaitu:

awk '/ ^ exim4-config / {$ 1 = ""; print} '

Pendek & sederhana. Bisa juga menyalurkan & menambahkan sed 's/\s\+//g'di akhir perintah untuk memangkas spasi utama
jumping_monkey

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

Ini memotong apa yang ada sebelum bidang yang diberikan nr., N, dan mencetak semua sisa baris, termasuk bidang nr.N dan mempertahankan jarak asli (tidak memformat ulang). Tidak masalah jika string bidang muncul juga di tempat lain dalam baris, yang merupakan masalah dengan jawaban daisaa.

Tentukan fungsi:

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

Dan gunakan seperti ini:

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

Output mempertahankan segalanya, termasuk spasi tambahan

Berfungsi dengan baik untuk file di mana '/ n' adalah pemisah record sehingga Anda tidak memiliki karakter baris baru di dalam baris. Jika Anda ingin menggunakannya dengan pemisah rekaman lain, gunakan:

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

sebagai contoh. Bekerja dengan baik dengan hampir semua file selama tidak menggunakan karakter heksadesimal. 1 di dalam garis.


4

Perintah awk berikut mencetak bidang N terakhir dari setiap baris dan di akhir baris mencetak karakter baris baru:

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

Temukan di bawah contoh yang mencantumkan konten direktori / usr / bin dan kemudian menyimpan 3 baris terakhir dan kemudian mencetak 4 kolom terakhir dari setiap baris menggunakan 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)}'

Pertama, Anda menemukan posisi awal kolom ketiga. Dengan substr Anda akan mencetak seluruh baris ($ 0) mulai dari posisi (dalam hal ini a) sampai akhir baris.


3

Nah, Anda dapat dengan mudah mencapai efek yang sama menggunakan ekspresi reguler. Dengan asumsi pemisah adalah spasi, ini akan terlihat seperti:

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

1
Saya akan menghindari regex. Mungkin lebih lambat dan lebih mudah untuk mengacaukan secara tidak sengaja.
Cascabel

1
Ini mempersingkatnya seperti ini: awk '{ sub(/([^ ]+ +){2}/, ""); print }'yang menghilangkan pola dua kali.
erik


2

Solusi Perl:

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

Opsi baris perintah ini digunakan:

  • -n memutar di sekitar setiap baris file input, jangan mencetak setiap baris secara otomatis

  • -l menghapus baris baru sebelum diproses, dan menambahkannya kembali setelahnya

  • -amode autosplit - memisahkan baris input ke dalam larik @F. Secara default, pemisahan di spasi kosong

  • -e jalankan kode perl

splice @F,0,2 menghapus kolom 0 dan 1 dengan rapi dari larik @F

join " ",@F menggabungkan elemen dari larik @F, menggunakan spasi di antara setiap elemen

Jika file masukan Anda dipisahkan dengan koma, bukan dipisahkan spasi, gunakan -F, -lane


Solusi Python:

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


1

Agak terlambat di sini, tetapi semua cara di atas sepertinya tidak berhasil. Coba ini, menggunakan printf, sisipkan spasi di antara masing-masing. Saya memilih untuk tidak memiliki baris baru di akhir.

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

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

mencetak rekaman mulai dari bidang ke-4 hingga bidang terakhir dengan urutan yang sama seperti di file aslinya


maaf, ini bukan jawaban yang benar. ini terlalu spesifik, tapi saya tidak tahu bagaimana cara menghapusnya
Massimo

1

Di Bash Anda dapat menggunakan sintaks berikut dengan parameter posisi:

while read -a cols; do echo ${cols[@]:2}; done < file.txt

Pelajari lebih lanjut: Menangani parameter posisi di Bash Hackers Wiki


0

Jika ini hanya tentang mengabaikan dua bidang pertama dan jika Anda tidak menginginkan spasi saat menutupi bidang tersebut (seperti yang dilakukan beberapa jawaban di atas):

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

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

Dua kolom pertama dikosongkan, sedmenghapus spasi terdepan.


-2

Dalam kolom AWK disebut field, maka NF adalah kuncinya

semua baris:

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

hanya baris pertama:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.