Menggunakan beberapa pembatas dalam awk

202

Saya memiliki file yang berisi baris-baris berikut:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

Dalam output di atas saya ingin mengekstrak 3 bidang (Nomor 2, 4 dan yang terakhir *.example.com). Saya mendapatkan output berikut:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

Bagaimana saya juga mengekstrak bidang terakhir dengan nama domain yang setelahnya '='? Bagaimana cara saya multiple delimitermengekstrak bidang?

Satish
sumber
2
Untuk menjawab pertanyaan saya yang sama tetapi berbeda, awkmenelan bidang ketika mereka kosong yang membentuk penomoran bidang. Saya berubah -F " "menjadi -F "[ ]"dan awktidak menelan ladang kosong lagi.
Adam

Jawaban:

324

Pembatas dapat berupa ekspresi reguler.

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

Menghasilkan:

tc0001   tomcat7.1    demo.example.com  
tc0001   tomcat7.2    quest.example.com  
tc0001   tomcat7.5    www.example.com
tertanam.kyle
sumber
42
Tentu saja, catproses tidak diperlukan: awk '...' file. Juga, akan lebih rapi untuk menggunakan pemisah bidang keluaran:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
glenn jackman
17
Pembatas awk bisa berupa ekspresi reguler ... ini membuat hariku!
das.cyklone
4
@ das.cyklone: ​​awk juga dapat memiliki beberapa pemisah, dengan |: ex: awk -F 'this|that|[=/]' '......' (berguna untuk membuat kata-kata / string memisahkan hal-hal) (perhatikan bahwa ini membuat ruang-ruang di fiels merasa antara 2 pemisah. Menambahkan juga |[ \t]+dapat berguna, tetapi dapat membuat hal-hal rumit ... karena sering ada spasi sebelum dan sesudah 'ini', ini akan membuat 2 bidang kosong ekstra muncul di antara ruang-ruang dan 'ini')
Olivier Dulac
Saya sudah mencoba ini pada 2 distro berbeda dan saya mendapatkan perilaku yang sama: Saya ingin mendapatkan port dari netstat -ntpl "netstat -ntpl | sed 's /: / /' awk '{print $ 5}'" berfungsi tetapi bisa melakukannya tanpa perpipaan doulbe Ini berfungsi tetapi saya tidak mengharapkan data di bidang 17: "netstat -ntpl | awk -F" |: "'{print $ 17}'"
louigi600
2
ya ... ini membuat saya mendapatkan apa yang saya inginkan: awk -F "[:] +" '/ \ / postmaster * $ / {print $ 5}'
louigi600
44

Kabar baik! awkpemisah bidang dapat berupa ekspresi reguler. Anda hanya perlu menggunakan -F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

Pengembalian:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

Sini:

  • -F"/|="mengatur pemisah bidang input ke salah satu /atau =. Kemudian, ini mengatur pemisah bidang keluaran ke sebuah tab.

  • -vOFS='\t'menggunakan -vbendera untuk mengatur variabel. OFSadalah variabel default untuk Pemisah Bidang Output dan disetel ke karakter tab. Bendera diperlukan karena tidak ada bawaan untuk OFS seperti -F.

  • {print $3, $5, $NF} mencetak bidang ke-3, ke-5 dan terakhir berdasarkan pemisah bidang input.


Lihat contoh lain:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

File ini memiliki dua bidang pemisah, #dan _. Jika kita ingin mencetak kolom kedua terlepas dari apakah separatornya satu atau yang lain, mari kita menjadikan keduanya pemisah!

$ awk -F"#|_" '{print $2}' file
how
am

Di mana file diberi nomor sebagai berikut:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
  1    2   3   4            1  2   3    4    5    6
fedorqui 'SO berhenti merugikan'
sumber
1
Terima kasih @ BUFU untuk hasil edit Anda. Saya menghapus referensi OFS untuk hanya fokus pada bagian FS, tetapi juga baik untuk memilikinya. Bersulang!
fedorqui 'SO stop harming'
5

Jika spasi putih Anda konsisten, Anda bisa menggunakannya sebagai pembatas, dan bukannya memasukkan \tsecara langsung, Anda bisa mengatur pemisah output dan itu akan disertakan secara otomatis:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'
Thor
sumber
3

Untuk pemisah bidang nomor apa pun 2melalui 5atau huruf aatau #atau spasi, di mana karakter pemisah harus diulang setidaknya 2 kali dan tidak lebih dari 6 kali, misalnya:

awk -F'[2-5a# ]{2,6}' ...

Saya yakin variasi ini ada menggunakan () dan parameter

genom
sumber
3

Perl one-liner:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

Opsi baris perintah ini digunakan:

  • -nloop di sekitar setiap baris dari file input, letakkan baris dalam $_variabel, jangan otomatis mencetak setiap baris

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

  • -amode autosplit - perl secara otomatis akan membagi jalur input ke dalam @Farray. Default untuk memisahkan di whitespace

  • -Fpengubah autosplit, dalam contoh ini terbagi menjadi salah satu /atau=

  • -e jalankan kode perl

Perl terkait erat dengan awk, namun, @Farray autosplit dimulai pada indeks $F[0]sementara bidang awk mulai dengan $ 1.

Chris Koknat
sumber
2

Yang lain adalah dengan menggunakan opsi -F tetapi meneruskannya regex untuk mencetak teks antara kurung kiri dan atau kanan ().

Konten file:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

Perintah:

awk -F"[()]" '{print $2}' filename

hasil:

smbw
smbt
smbn
smbs

Menggunakan awk untuk hanya mencetak teks di antara []:

Gunakan awk -F'[][]' tetapi awk -F'[[]]'tidak akan berfungsi.

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html

Stan Lovisa
sumber
Jawaban Anda muncul dalam antrian penghapusan karena 9 kali dari 10, pengguna dengan 1 reputasi menautkan ke blog mereka sendiri biasanya adalah spam. Tapi milikmu adalah pengecualian dari aturan itu. 10 tahun terakhir konten ada tambang emas, mudah-mudahan Anda punya rencana untuk mengabadikannya.
Eric Leschinski
0

Saya melihat banyak jawaban sempurna ada di papan tulis, tetapi masih ingin mengunggah kode saya juga,

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'

Sadhun
sumber
2
print $3 " " $5 " " $7dapat dicetak sama seperti print $3, $5, $7. Juga, saya tidak melihat keuntungan menggunakan awk dan kemudian mem-pip ke sed. Secara umum, awk dapat mencukupi dan yang lainnya menjawab menunjukkan itu.
fedorqui 'SO stop harming'