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?


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

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

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}'

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


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.


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


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'


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'
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.