Teks ini hanya mengacu pada implementasi GNU awk yang dikenal sebagai gawk Witch adalah yang paling banyak digunakan dan hadir dengan distribusi Linux / UNIX modern.
[Panduan Pengguna AWK GNU] [GNU-AWK] adalah rujukannya, untuk contoh-contoh yang saya gunakan kasus dunia nyata yang diambil terutama dari jawaban [stackoverflow] saya [jadi].
AWK adalah bahasa yang mirip dengan Perl, hanya jauh lebih elegan.
- Arnold Robbins
AWK adalah bahasa pemrograman yang dirancang untuk pemrosesan teks dan biasanya digunakan sebagai alat ekstraksi dan pelaporan data. Ini adalah fitur standar dari sebagian besar sistem operasi seperti UNIX.
awk ...Namanya berasal dari nama keluarga penulisnya - Alfred A Ho, Peter W Einberger, dan Brian K Ernighan.
awk ...Pencarian untuk baris yang berisi pola tertentu dalam file atau input standar.
Sebagian besar digunakan untuk ekstraksi data dan pelaporan seperti merangkum informasi dari output program utilitas lainnya.
Sintaks C-like .
Data Didorong: Ini menggambarkan data yang ingin Anda kerjakan dan kemudian tindakan apa yang harus dilakukan saat Anda menemukannya.
pattern { action }
pattern { action }Jika programnya pendek :
awk ' program ' input-file1 input-file2CATATAN: Waspadalah terhadap masalah kutipan shell 1 .
cmd | awk ' program ' CATATAN: pipe mengarahkan output dari perintah kiri ( cmd ) ke input perintah awk 2 .
Ketika kode panjang , biasanya lebih nyaman untuk memasukkannya ke dalam file dan menjalankannya dengan perintah seperti ini:
awk -f program-file input-file1 input-file2
cmd | awk -f program-file Atau cukup dapat dieksekusi seperti shebang :
#! /bin/awk -f
BEGIN { print " hello world!! " } -F fs Atur variabel FS ke fs .
-v var=val Atur variabel var ke val nilai sebelum eksekusi program dimulai.
Catatan : Ini dapat digunakan lebih dari sekali, mengatur variabel lain setiap kali.
Pola atau blok khusus ini memasok tindakan startup dan pembersihan untuk program awk .
BEGIN{
// initialize variables
}
{
/pattern/ { action }
}
END{
// cleanup
}BEGIN sebelum catatan input pertama dibaca, END setelah semua input dikonsumsi.
$ echo " hello " | awk ' BEGIN{print "BEGIN";f=1}
{print $f}
END{print "END"} '
BEGIN
hello
ENDgrepping jika Anda memiliki awk ?? $ cat lorem_ipsum.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.$ grep dolor lorem_ipsum.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.$ awk ' /dolor/ ' lorem_ipsum.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.Catatan: Jika tindakan tidak diberikan tindakan default adalah mencetak catatan yang cocok dengan pola yang diberikan.
Tapi ... bagaimana kita bisa mengetahui kata pertama dan terakhir dari setiap baris?
Tentu saja grep bisa, tetapi membutuhkan dua langkah:
$ grep -Eo ' ^[^ ]+ ' lorem_ipsum.dat
Lorem
Maecenas
Nunc
Curabitur
Lorem
Aliquam$ grep -Eo ' [^ ]+$ ' lorem_ipsum.dat
elit.
condimentum.
ex.
tellus.
elit.
ultrices. Mari kita lihat awk beraksi di sini:
$ awk ' {print $1,$NF} ' lorem_ipsum.dat
Lorem elit.
Maecenas condimentum.
Nunc ex.
Curabitur tellus.
Lorem elit.
Aliquam ultrices. awk membagi input untuk program Anda menjadi catatan dan bidang .
Catatan dipisahkan oleh karakter yang disebut rekaman pemisah RS . Secara default , pemisah rekaman adalah karakter baru UNIX n .
Inilah sebabnya mengapa catatan, secara default , satu baris .
Selain itu awk memiliki ORS Output Record Separator untuk mengontrol cara catatan disajikan ke stdout .
RS dan ORS harus dilampirkan dalam tanda kutip , yang menunjukkan konstanta string.
Untuk menggunakan karakter yang berbeda atau regex cukup tetapkan ke variabel RS atau / dan ORS :
BEGIN , sebelum input apa pun diproses, sehingga catatan pertama dibaca dengan pemisah yang tepat.Contoh:
$ awk ' BEGIN{RS=" *, *";ORS="<<<---n"}
{print $0} ' lorem_ipsum.dat
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci <<< ---
euismod id nisi eget <<< ---
interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat <<< ---
et facilisis neque ultrices.
<<< --- $ awk ' {print $0} ' RS= " *, * " ORS= " <<<---n " lorem_ipsum.dat
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci <<< ---
euismod id nisi eget <<< ---
interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet <<< ---
consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat <<< ---
et facilisis neque ultrices.
<<< --- Catatan awk secara otomatis diuraikan atau dipisahkan menjadi potongan -potongan yang disebut Fields .
Secara default, bidang dipisahkan oleh whitespace (string satu atau lebih spasi, tab, atau Newline), seperti kata -kata dalam baris.
Untuk merujuk ke bidang dalam program awk , Anda menggunakan tanda $ dolar diikuti oleh jumlah bidang yang Anda inginkan.
Dengan demikian, $1 mengacu pada bidang pertama, $2 ke yang kedua, dan seterusnya.
Penting : $0 mewakili seluruh catatan input.
$ awk ' {print $3} ' lorem_ipsum.dat
dolor
erat
orci,
dapibus
dolor
mauris NF adalah variabel yang telah ditentukan nilainya adalah jumlah bidang dalam catatan saat ini . Jadi, $NF akan selalu menjadi bidang terakhir dari catatan.
$ awk ' {print NF} ' lorem_ipsum.dat
8
7
10
4
8
10Vs.
$ awk ' {print $NF} ' lorem_ipsum.dat
elit.
condimentum.
ex.
tellus.
elit.
facilisis. FS memegang nilai pemisah lapangan , nilai ini adalah string karakter tunggal atau regex yang cocok dengan pemisahan antara bidang dalam catatan input.
Nilai default adalah " " , string yang terdiri dari satu ruang. Sebagai pengecualian khusus, nilai ini berarti bahwa urutan spasi , tab , dan/atau newline adalah pemisah tunggal.
Dengan cara yang sama dengan ORS kami memiliki variabel OFS untuk mengelola bagaimana bidang kami akan dikirim ke aliran output.
$ cat /etc/group
nobody: * :-2:
nogroup: * :-1:
wheel: * :0:root
daemon: * :1:root
kmem: * :2:root
sys: * :3:root
tty: * :4:root$ awk ' !/^(_|#)/&&$1=$1 ' FS= " : " OFS= " <-> " /etc/group
nobody < - > * < - > - 2< - >
nogroup < - > * < - > - 1< - >
wheel < - > * < - > 0 < - > root
daemon < - > * < - > 1 < - > root
kmem < - > * < - > 2 < - > root
sys < - > * < - > 3 < - > root
tty < - > * < - > 4 < - > root Catatan : ummm ... $1=$1 ???? 3
Mengingat catatan dan bidang , sekarang siap untuk memahami kode kami sebelumnya:
$ awk ' {print $1,$NF} ' lorem_ipsum.dat
Lorem elit.
Maecenas condimentum.
Nunc ex.
Curabitur tellus.
Lorem elit.
Aliquam ultrices.Ini adalah dua variabel bawaan yang berguna:
NR : Jumlah catatan input awk telah diproses sejak awal eksekusi program.
FNR : Nomor catatan saat ini dalam file saat ini, awk mengatur ulang FNR ke nol setiap kali memulai file input baru.
$ cat n1.dat
one
two$ cat n2.dat
three
four$ awk ' {print NR,FNR,$0} ' n1.dat n2.dat
1 1 one
2 2 two
3 1 three
4 2 fourString format sangat mirip dengan yang ada di iso c .
Sintaksis:
printf format, item1, item2, …
$ awk ' {printf "%20s <-> %sn",$1,$NF} ' lorem_ipsum.dat
Lorem < - > elit.
Maecenas < - > condimentum.
Nunc < - > ex.
Curabitur < - > tellus.
Lorem < - > elit.
Aliquam < - > ultrices. Output dari print dan printf diarahkan ke output standar secara default tetapi kami dapat menggunakan pengalihan untuk mengubah tujuan.
Pengalihan dalam awk ditulis seperti pengalihan dalam perintah shell , kecuali bahwa mereka ditulis di dalam program awk .
$ awk ' BEGIN{print "hello">"hello.dat"} ' $ awk ' BEGIN{print "world!">>"hello.dat"} ' $ cat hello.dat
hello
world !Dimungkinkan juga untuk mengirim output ke program lain melalui pipa :
$ awk ' BEGIN{sh="/bin/sh";print "date"|sh;close(sh)} '
dom nov 13 18:36:25 CET 2016 [Streams] dapat diarahkan ke stdin , stdout dan stderr .
Misalnya, kita dapat menulis pesan kesalahan ke stderr seperti ini:
$ awk ' BEGIN{print "Serious error detected!" > "/dev/stderr"} '
Serious error detected ! Dalam AWK array itu asosiatif , masing -masing adalah kumpulan pasangan , indeks - nilai , di mana angka atau string apa pun dapat berupa indeks.
Tidak ada deklarasi yang dibutuhkan; Pasangan baru dapat ditambahkan kapan saja.
| Indeks | Nilai |
|---|---|
| "Perro" | "anjing" |
| "Gato" | "kucing" |
| "uno" | "satu" |
| 1 | "satu" |
| 2 | "dua" |
Untuk merujuk array:
array[index-expression]
Untuk menetapkan nilai:
array[index-expression] = value
Untuk memeriksa apakah kunci diindeks:
indx in array
Untuk mengulanginya:
for (var in array) {
var, array[var]
}Menggunakan nilai numerik sebagai indeks dan melestarikan pesanan:
for (i = 1 ; i < = max_index ; i++) {
print array[i]
}Contoh Lengkap:
$ cat dict.dat
uno one
dos two
tres three
cuatro fourawk ' {dict[$1]=$2}
END{if ("uno" in dict)
print "Yes we have uno in dict!"
if (!("cinco" in dict))
print "No , cinco is not in dict!"
for (esp in dict){
print esp, "->" ,dict[esp]
}
} ' dict.datMemberi Anda:
Yes we have uno in dict !
No , cinco is not in dict !
uno - > one
dos - > two
tres - > three
cuatro - > four gawk tidak mengurutkan array secara default:
awk ' BEGIN{
a[4]="four"
a[1]="one"
a[3]="three"
a[2]="two"
a[0]="zero"
exit
}
END{for (idx in a){
print idx, a[idx]
}
} ' 4 four
0 zero
1 one
2 two
3 threeTetapi Anda dapat memanfaatkan [Procinfo] untuk menyortir:
awk ' BEGIN{
PROCINFO["sorted_in"] = "@ind_num_asc"
a[4]="four"
a[1]="one"
a[3]="three"
a[2]="two"
a[0]="zero"
exit
}
END{for (idx in a){
print idx, a[idx]
}
} ' 0 zero
1 one
2 two
3 three
4 four gensub(regexp, replacement, how [, target]) : adalah fungsi paling canggih untuk penggantian string.
Dan alternatif mereka yang lebih sederhana:
gsub(regexp, replacement [, target])
sub(regexp, replacement [, target])
Memiliki file ini:
$ cat lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.Kami akan menukar posisi kata -kata yang ditempatkan di kiri dan kanan setiap koma.
$ awk ' {print gensub(/([^ ]+)( *, *)([^ ]+)/,
"\3\2\1", "g")} ' lorem.dat
Lorem ipsum dolor sit consectetur, amet adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim euismod, orci id nisi interdum, eget cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit consectetur, amet adipiscing elit.
Aliquam interdum mauris volutpat nisl et, placerat facilisis. Menggunakan gensub kami menangkap tiga kelompok dan kemudian kami menukar pesanan.
Untuk mengilustrasikan tindakan yang lebih sederhana, mari kita ubah titik untuk koma :
awk ' $0=gensub(/./, ",", "g") ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Maecenas pellentesque erat vel tortor consectetur condimentum,
Nunc enim orci, euismod id nisi eget, interdum cursus ex,
Curabitur a dapibus tellus,
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Aliquam interdum mauris volutpat nisl placerat, et facilisis, Menggunakan alternatif gsub :
awk ' gsub(/./, ",") ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Maecenas pellentesque erat vel tortor consectetur condimentum,
Nunc enim orci, euismod id nisi eget, interdum cursus ex,
Curabitur a dapibus tellus,
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
Aliquam interdum mauris volutpat nisl placerat, et facilisis,Opsi ini tampak lebih baik ketika tidak ada penangkapan grup .
Fungsi menarik lainnya adalah index dan substr .
index(in, find)
substr(string, start [, length ])
Bekerja seperti ini:
$ awk ' BEGIN{t="hello-world";print index(t, "-")} '
6$ awk ' BEGIN{t="hello-world";print substr(t,index(t, "-")+1)} '
world Fungsi split digunakan untuk membuat array dari string yang membaginya dengan arang pemisah , ia mengembalikan jumlah elemen array yang dibuat.
split(string, array [, fieldsep [, seps ] ])
$ cat passwd
jd001:x:1032:666:Javier Diaz:/home/jd001:/bin/rbash
ag002:x:8050:668:Alejandro Gonzalez:/home/ag002:/bin/rbash
jp003:x:1000:666:Jose Perez:/home/jp003:/bin/bash
ms004:x:8051:668:Maria Saenz:/home/ms004:/bin/rbash
rc005:x:6550:668:Rosa Camacho:/home/rc005:/bin/rbash$ awk ' n=split($0, a, ":"){print n, a[n]} ' passwd
7 /bin/rbash
7 /bin/rbash
7 /bin/bash
7 /bin/rbash
7 /bin/rbashCatatan : Ini bisa dilakukan dengan cara yang jauh lebih sederhana:
$ awk ' {print NF,$NF} ' FS= ' : ' passwd
7 /bin/rbash
7 /bin/rbash
7 /bin/bash
7 /bin/rbash
7 /bin/rbashTulis fungsi kustom cukup sederhana:
awk ' function test(m)
{
printf "This is a test func, parameter: %sn", m
}
BEGIN{test("param")} 'Beri Kami:
This is a test func, parameter: param Kami juga dapat mengembalikan ekspresi menggunakan pernyataan return :
awk ' function test(m)
{
return sprintf("This is a test func, parameter: %s", m)
}
BEGIN{print test("param")} 'Parsing berdasarkan parameter adalah satu -satunya cara untuk membuat variabel lokal di dalam fungsi.
Nilai skalar dilewatkan oleh nilai dan array dengan referensi, sehingga setiap perubahan yang dilakukan pada array di dalam fungsi akan tercermin dalam ruang lingkup global:
awk ' function test(m)
{
m[0] = "new"
}
BEGIN{m[0]=1
test(m)
exit
}
END{print m[0]} 'Output:
newTantangan kami :
01. Kata catatan kedua dari sebuah catatan.
02. Mengganti catatan.
03. Tempatkan titik koma di akhir setiap catatan.
04. Tempatkan koma di antara setiap kata.
05. Semua bersama -sama?
06. Mengalihkan catatan aneh ke file dan bahkan yang lain.
07. Diberikan file kata sandi dapatkan bidang yang hilang.
08. Pertukaran Lapangan.
09. Traceroute Hacking.
10. Dimana anak -anak saya?
11. Agregasi Data.
12. Catatan antara dua pola.
13. Transformasi Lapangan.
14. Catatan ke kolom.
15. Pemrosesan File FASTA.
16. Pelaporan Kompleks.
17. File joiner.
18. Passwd dan Group.
19. Koneksi Pengguna.
20. Uptime Total Load Average.
Memiliki file sumber ini:
$ cat lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.$ awk ' {print $(NF-1)} ' lorem.dat
adipiscing
consectetur
cursus
dapibus
adipiscing
neque Tidak terlalu banyak untuk dijelaskan di sini, NF menyimpan jumlah bidang dalam catatan saat ini, sehingga NF-1 poin ke lapangan sebelum terakhir dan $(NF-1) akan menjadi nilainya.
Tugas kami, Substitusi Catatan File, Baris Ketiga Harus Menjadi:
This not latin
Tidak ada yang lebih sederhana, hanya bermain di sekitar NR ( jumlah rekaman ).
Kode:
$ awk ' NR==3{print "This is not latin";next}{print} ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
This is not latin
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis. Solusi alternatif untuk menghindari pernyataan next : Tetapkan baris baru ke catatan lengkap $0 .
Contoh:
$ awk ' NR==3{$0="This is not latin"}1 ' lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
This is not latin
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.$ awk ' 1 ' ORS= " ;n " lorem.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ;
Maecenas pellentesque erat vel tortor consectetur condimentum. ;
Nunc enim orci, euismod id nisi eget, interdum cursus ex. ;
Curabitur a dapibus tellus. ;
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ;
Aliquam interdum mauris volutpat nisl placerat, et facilisis neque ultrices. ; Karena RS default adalah garis istirahat UNIX n kita hanya perlu mengawali titik koma dengan OFS catatan output.
1 yang aneh itu? 4
$ awk ' {$1=$1}1 ' OFS= ' , ' lorem.dat
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit.
Maecenas,pellentesque,erat,vel,tortor,consectetur,condimentum.
Nunc,enim,orci,,euismod,id,nisi,eget,,interdum,cursus,ex.
Curabitur,a,dapibus,tellus.
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit.
Aliquam,interdum,mauris,volutpat,nisl,placerat,,et,facilisis,neque,ultrices. Bagian paling signifikan dari kode ini adalah bagaimana ia memaksa rekonstruksi catatan dengan $1=$1 untuk nilai OFS saat ini.
$ awk ' {$1=$1}1 ' OFS= ' , ' ORS= ' ;n ' lorem.dat
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit. ;
Maecenas,pellentesque,erat,vel,tortor,consectetur,condimentum. ;
Nunc,enim,orci,,euismod,id,nisi,eget,,interdum,cursus,ex. ;
Curabitur,a,dapibus,tellus. ;
Lorem,ipsum,dolor,sit,amet,,consectetur,adipiscing,elit. ;
Aliquam,interdum,mauris,volutpat,nisl,placerat,,et,facilisis,neque,ultrices. ; Hanya bermain dengan output vars: OFS dan ORS .
Mari kita mulai dengan solusi akhir:
$ awk ' NR%2{print > "even.dat";next}
{print > "odd.dat"} ' lorem.dat$ cat even.dat
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Lorem ipsum dolor sit amet, consectetur adipiscing elit$ cat odd.dat
Maecenas pellentesque erat vel tortor consectetur condimentum.
Curabitur a dapibus tellus.
Aliquam interdum mauris volutpat nisl placerat, et facilisis. Fungsi [modulo] ( % ) menemukan sisanya setelah pembagian untuk nomor catatan saat ini NR dibagi dua:
$ awk ' {print NR%2} ' lorem.dat
1
0
1
0
1
0 Sejauh kita sekarang, dalam awk 1 benar dan 0 false . Kami mengarahkan ulang output kami mengevaluasi fakta ini.
next membutuhkan perhatian khusus, itu memaksa awk untuk segera menghentikan proses catatan saat ini dan beralih ke yang berikutnya.
Dengan cara ini kami menghindari kondisi ganda yang akan terlihat seperti ini:
awk ' NR % 2{print > "even.dat"}
!NR % 2{print > "odd.dat"} ' lorem.dat$ cat /etc/passwd
jd001:x:1032:666:Javier Diaz::/bin/rbash
ag002:x:8050:668:Alejandro Gonzalez::/bin/rbash
jp003:x:1000:666:Jose Perez::/bin/bash
ms004:x:8051:668:Maria Saenz::/bin/rbash
rc005:x:6550:668:Rosa Camacho::/bin/rbash Mari kita asumsikan direktori home dengan mengawali string tetap "/home/" ke nama pengguna :
$ awk ' $6="/home/"$1 ' FS= ' : ' OFS= ' : ' /etc/passwd
jd001:x:1032:666:Javier Diaz:/home/jd001:/bin/rbash
ag002:x:8050:668:Alejandro Gonzalez:/home/ag002:/bin/rbash
jp003:x:1000:666:Jose Perez:/home/jp003:/bin/bash
ms004:x:8051:668:Maria Saenz:/home/ms004:/bin/rbash
rc005:x:6550:668:Rosa Camacho:/home/rc005:/bin/rbashLangkah pertama kami harus mempertimbangkan pemisah lapangan, usus besar, untuk input dan juga untuk output.
Maka kita perlu menemukan posisi lapangan void, 6 untuk contoh ini.
Akhirnya, kami menyusun nilai yang diperlukan menggunakan string yang diberikan dan login pengguna yang disimpan di bidang pertama.
print tidak diperlukan karena nilai pengembalian penugasan $6 akan selalu benar dan tindakan default yang awk adalah mencetak catatan yang terpengaruh.
Tujuan kami: Bidang terakhir harus menjadi yang pertama dan pertama menjadi yang terakhir.
Kode akhir:
$ awk -F : ' {last=$1;$1=$NF;$NF=last}1 ' FS= " : " OFS= ' : ' /etc/passwd
/bin/rbash:x:1032:666:Javier Diaz:/home/jd001:jd001
/bin/rbash:x:8050:668:Alejandro Gonzalez:/home/ag002:ag002
/bin/bash:x:1000:666:Jose Perez:/home/jp003:jp003
/bin/rbash:x:8051:668:Maria Saenz:/home/ms004:ms004
/bin/rbash:x:6550:668:Rosa Camacho:/home/rc005:rc005 Kami bermain dengan variabel menengah yang digunakan untuk menyimpan nilai bidang pertama, kami menukar nilainya dengan yang terakhir, akhirnya kami menetapkan variabel last ke $NF ( $NF=last ).
Memiliki output ini:
$ traceroute -q 1 google.com 2> /dev/null
1 hitronhub.home (192.168.1.1) 5.578 ms
2 217.217.0.1.dyn.user.ono.com (217.217.0.1) 9.732 ms
3 10.127.54.181 (10.127.54.181) 10.198 ms
4 62.42.228.62.static.user.ono.com (62.42.228.62) 35.519 ms
5 72.14.235.20 (72.14.235.20) 26.003 ms
6 216.239.50.133 (216.239.50.133) 25.678 ms
7 mad01s24-in-f14.1e100.net (216.58.211.238) 25.019 msKita perlu menghitung paket total waktu bepergian .
$ traceroute -q 1 google.com 2> /dev/null |
awk ' {total+=$(NF-1)}
END{print "Total ms: "total} '
Total ms: 153.424Karena tidak ada kondisi yang ditentukan, tindakan dieksekusi untuk semua catatan .
total+=$(NF-1) : Variabel total digunakan untuk mengakumulasi nilai setiap rekor bidang kedua dari pendahuluan $(NF-1) .
Akhirnya, kami menggunakan aturan END untuk menunjukkan nilai total akhir.
Pekerjaan kami: Dapatkan proses tergantung shell kami.
$ echo $$
51026Hal pertama : Luncurkan proses latar belakang.
$ sleep 10 & sleep 15 & sleep 20 &
[1] 86751
[2] 86752
[3] 86753 Menggunakan utilitas ps , awk akan mencari bidang ketiga yang dikenal sebagai PPID .
Catatan : Kami menggunakan -v untuk mengatur PPID VAR sebelum eksekusi program dimulai.
$ ps -ef | awk -v ppid= $$ ' $3==ppid '
501 86751 51026 0 7:57PM ttys001 0:00.00 sleep 10
501 86752 51026 0 7:57PM ttys001 0:00.00 sleep 15
501 86753 51026 0 7:57PM ttys001 0:00.00 sleep 20
0 86754 51026 0 7:57PM ttys001 0:00.00 ps -ef
501 86755 51026 0 7:57PM ttys001 0:00.00 awk $3 ==51026Kami hanya perlu tidur :
$ ps -ef | awk -v ppid= $$ ' $3 == ppid && /slee[p]/
{print $2" -> "$5} '
86751 - > 7:57PM
86752 - > 7:57PM
86753 - > 7:57PM Solusinya membutuhkan kondisi baru untuk ditambahkan: Temukan pola tidur di catatan /slee[p]/ .
Tindakan yang dipicu adalah mencetak bidang kedua $2 dengan dudukan untuk PID dan $5 kelima, cap waktu .
Memiliki file ini:
$ cat ips.dat
IP BYTES
81.220.49.127 328
81.220.49.127 328
81.220.49.127 329
81.220.49.127 367
81.220.49.127 5302
81.226.10.238 328
81.227.128.93 84700 Tugas kami adalah menghitung berapa banyak byte per IP yang diproses.
$ awk ' NR>1{ips[$1]+=$2}
END{for (ip in ips){print ip, ips[ip]}} ' ips.dat
81.220.49.127 6654
81.227.128.93 84700
81.226.10.238 328Banyak hal di sini untuk dijelaskan.
NR>1{ips[$1]+=$2} : Tindakan ips[$1]+=$2 hanya dieksekusi ketika nomor catatan saat ini lebih besar dari satu NR>1 . Ini diperlukan untuk menghindari tajuk.
ips adalah array yang diindeks oleh nilai IP (bidang $1 ), untuk setiap kunci yang akan kami kumpulkan dalam nilai bidang kedua.
Perhatikan fakta penting , jika kunci tidak ada dalam array , awk menambahkan elemen baru ke struktur , jika tidak akan memperbarui nilai sebelumnya yang ditunjuk oleh kunci itu (seperti dalam contoh kami).
Aturan END hanya digunakan untuk mengulangi array dengan indeks dan nilai.
Kode ini dapat ditulis ulang dengan cara yang berbeda untuk menghindari penggunaan array dan mempertahankan pesanan yang dimanfaatkan dari file IPS yang diurutkan:
awk ' NR==1{next}
lip && lip != $1{print lip,sum;sum=0}
{sum+=$2;lip=$1}
END{print lip,sum} ' ips.dat
81.220.49.127 6654
81.226.10.238 328
81.227.128.93 84700 NR==1{next} : Bypass header.
lip && lip != $1{print lip,sum;sum=0} : Di sini kita menggunakan var bernama lip ( last-ip ). lip && lip != $1 Saat lip tidak nol dan nilainya tidak sama dengan bidang pertama (yang memegang IP saat ini) tindakan yang dipicu adalah mencetak lip dan sum jumlah total byte untuk IP terakhir. Kemudian kami menginisialisasi sum=0 .
Triknya jelas, setiap kali perubahan IP ( $1 ) kami menunjukkan statistik yang sebelumnya.
{sum+=$2;lip=$1} : Untuk memperbarui sum+=$2 dan tetapkan IP saat ini ke lip : lip=$1 . Ini adalah langkah terakhir dari pemrosesan rekaman kami.
Blok END digunakan untuk mencetak nilai yang tertunda .
Kode ini menjaga pesanan, tetapi menurut saya , ini datang dengan mengorbankan kompleksitas yang meningkat secara signifikan.
Tugas kami adalah dua mengekstrak garis antara dan OUTPUT dan END .
$ cat pat.dat
test -3
test -2
test -1
OUTPUT
top 2
bottom 1
left 0
right 0
page 66
END
test 1
test 2
test 3 Ini adalah contoh klasik yang digunakan untuk menggambarkan bagaimana pencocokan pola bekerja dalam awk dan tindakan rekannya yang saya mendedikasikan [posting] lengkap.
$ awk ' /END/{flag=0}flag;/OUTPUT/{flag=1} ' pat.dat
top 2
bottom 1
left 0
right 0
page 66 Berdasarkan nilai variabel flag , itu akan benar ( 1 ) ketika OUTPUT pola awal ditemukan dan false ( 0 ) ketika tag END tercapai.
Untuk menghindari langkah tambahan, urutan tindakan sangat penting , jika kita mengikuti urutan logika :
$ awk ' /OUTPUT/{flag=1}flag;/END/{flag=0} ' pat.dat
OUTPUT
top 2
bottom 1
left 0
right 0
page 66
ENDTag pola ditampilkan melalui output.
Alasannya: setelah pola OUTPUT ditemukan, bendera diaktifkan, karena tindakan berikutnya tergantung pada bendera ini catatan dicetak.
Kita dapat menghindari perilaku ini menempatkan aktivasi bendera sebagai langkah terakhir dari aliran.
Misalkan file ini:
$ cat space.dat
10.80 kb
60.08 kb
35.40 kb
2.20 MB
1.10 MB
40.80 kb
3.15 MB
20.50 kbTugas kami adalah menghitung bobot total catatan kami dalam mega byte :
$ awk ' {total+= $1 / ($2=="kb" ? 1024: 1)}
END{print total} ' space.dat
6.61365Untuk memahami cara kerjanya, satu konsep harus jelas, operator [ternary] (subjek pos lama).
total akan digunakan untuk mengumpulkan divis dari bidang pertama $1 dengan $2 kedua yang akan menahan nilai yang diberikan oleh operator ternary : 1024 ketika $2 sama dengan kb dan 1 jika tidak ada transformasi yang diperlukan.
Akhirnya, kami mencetak nilai total di blok END .
Sumber Asli:
$ cat group.dat
string1
string2
string3
string4
string5
string6
string8Misi kami adalah untuk mengelompokkan catatan dalam blok tiga kolom seperti ini:
string1 string2 string3
string4 string5 string6
string8 Ini mungkin tampak kompleks, tetapi menjadi lebih sederhana jika kita memahami cara menggunakan OFS bidang output :
$ awk ' ORS = NR%3 ? FS : RS; END{print "n"} ' group.dat
string1 string2 string3
string4 string5 string6
string8 Jika kita mengatur ORS ke karakter kosong , nilai default FS , semua output akan menjadi satu baris:
$ awk ' ORS=FS; END{print "n"} ' group.dat
string1 string2 string3 string4 string5 string6 string7 ORS = NR%3 ? FS : RS : Akhirnya kami menggunakan operator ternary (dijelaskan sesaat sebelumnya) untuk mengevaluasi [modulo] NR%3 hasil dari divisi nomor bidang saat ini NR oleh tiga.
Jika sisanya benar , ORS menjadi FS , ruang kosong , jika tidak, nilai default RS akan ditetapkan, Break Jalur UNIX n .
Dalam bioinformatika , [FASTA] adalah format file berbasis teks.
Memiliki contoh berikut:
$ cat fasta.dat
> header1
CGCTCTCTCCATCTCTCTACCCTCTCCCTCTCTCTCGGATAGCTAGCTCTTCTTCCTCCT
TCCTCCGTTTGGATCAGACGAGAGGGTATGTAGTGGTGCACCACGAGTTGGTGAAGC
> header2
GGT
> header3
TTATGATKami membutuhkan panjang total setiap urutan , dan resume akhir .
Harus terlihat seperti ini:
> header1
117
> header2
3
> header3
7
3 sequences, total length 127 awk adalah alat yang sempurna untuk upaya pelaporan ini, untuk contoh ini akan kami gunakan:
awk ' /^>/ { if (seqlen) {
print seqlen
}
print
seqtotal+=seqlen
seqlen=0
seq+=1
next
}
{
seqlen += length($0)
}
END{print seqlen
print seq" sequences, total length " seqtotal+seqlen
} ' fasta.dat
Tindakan pertama terikat pada deteksi header /^>/ , itu karena semua header bintang dengan > karakter.
Ketika seqlen tidak membatalkan nilainya, yang memegang panjang urutan sebelumnya, dicetak ke stdout yang terpasang pada header baru. seqtotal diperbarui dan seqlen diinisialisasi untuk melayani urutan berikutnya. Akhirnya, kami memecahkan pemrosesan rekaman lebih lanjut dengan next .
Tindakan kedua {seqlen += length($0)} digunakan untuk memperbarui seqlen yang menjumlahkan total panjang catatan.
Tujuan aturan END adalah untuk menunjukkan urutan dan total yang belum dicetak .
Trik di sini adalah mencetak panjang urutan sebelumnya ketika kami menemukan header baru .
Ketika kami memproses rekaman pertama seqlen tidak memiliki nilai sehingga kami melewatkan visualisasi.
Sumber:
$ cat report.dat
snaps1: Counter: 4966
Opens: Counter: 357283
Instance: s.1.aps.userDatabase.mount275668.attributes
snaps1: Counter: 0
Opens: Counter: 357283
Instance: s.1.aps.userDatabase.test.attributes
snaps1: Counter: 5660
Opens: Counter: 37283
Instance: s.1.aps.userDatabase.mount275000.attributes Tugas kami: Buat laporan untuk memvisualisasikan snaps dan instance tetapi hanya ketika tag counter pertama lebih besar dari nol .
Output yang diharapkan:
snaps1: Counter: 4966
Instance: s.1.aps.userDatabase.mount275668.attributes
snaps1: Counter: 5660
Instance: s.1.aps.userDatabase.mount275000.attributesKami bermain lagi di sekitar pola dan bendera :
awk ' {$1=$1}
/snaps1/ && $NF>0{print;f=1}
f && /Instance/ {print;f=0} ' report.dat Untuk setiap catatan, tindakan pertama dieksekusi , ini memaksa awk untuk membangun kembali seluruh catatan , menggunakan nilai -nilai saat ini untuk OFS 3 .
Trik ini memungkinkan kami untuk mengonversi beberapa pemisah ruang menjadi char tunggal , nilai default untuk pemisah bidang output.
Mari kita lihat ini:
$ awk ' 1 ' text.dat
one two
three four$ awk ' $1=$1 ' text.dat
one two
three four Tindakan kedua dipicu ketika pola ditemukan dan bidang terakhir lebih besar dari nol /snaps1/ && $NF>0 .
awk mencetak catatan dan menetapkan nilai sebenarnya ke print;f=1 .
Langkah terakhir: Ketika flag benar dan pola instance di baris f && /Instance/ , tunjukkan baris dan nonaktifkan bendera: print;f=0 .
Misalkan dua arsip:
$ cat join1.dat
3.5 22
5. 23
4.2 42
4.5 44$ cat join2.dat
3.5
3.7
5.
6.5 Kami membutuhkan catatan dari yang pertama join1.dat ketika bidang pertama berada di yang kedua join2.dat .
Output harus:
3.5 22
5. 23Kami dapat menggunakan utilitas gabungan unix , tentu saja, tetapi kami perlu mengurutkan file pertama:
$ join <( sort join1.dat ) join2.dat
3.5 22
5. 23 Tidak diperlukan dalam awk :
$ awk ' NR == FNR{a[$1];next}
$1 in a ' join2.dat join1.datMari kita pelajari filter dan tindakannya:
NR == FNR : Nomor catatan sama dengan nomor file merekam berarti bahwa kami memproses file pertama yang diuraikan ke awk : join2.dat .
Tindakan pasangan a[$1];next adalah menambahkan nilai batal baru ke array yang diindeks oleh bidang pertama. Pernyataan next akan memecahkan pemrosesan rekaman dan meneruskan aliran ke yang berikutnya .
Untuk tindakan kedua NR != FNR diterapkan secara implisit dan hanya mempengaruhi untuk join1.dat , kondisi kedua adalah $1 in a yang akan benar ketika bidang pertama dari join1.dat adalah kunci array.
Ini untuk unix klasik :
$ cat /etc/group
dba:x:001:
netadmin:x:002:$ cat /etc/passwd
jd001:x:1032:001:Javier Diaz:/home/jd001:/bin/rbash
ag002:x:8050:002:Alejandro Gonzalez:/home/ag002:/bin/rbash
jp003:x:1000:001:Jose Perez:/home/jp003:/bin/bash
ms004:x:8051:002:Maria Saenz:/home/ms004:/bin/rbash
rc005:x:6550:002:Rosa Camacho:/home/rc005:/bin/rbashTujuan kami, laporan seperti ini:
d001:dba
ag002:netadmin
jp003:dba
ms004:netadmin
rc005:netadminKami membutuhkan beberapa aliran file saat kami belajar dalam contoh terakhir kami:
$ awk -F : ' NR == FNR{g[$3]=$1;next}
$4 in g{print $1""FS""g[$4]} ' /etc/group /etc/passwd Untuk memproses /etc/group kami mengulangi perbandingan NR == FNR kemudian menyimpan nama grup $1 yang diindeks oleh ID $3 : g[$3]=$1 . Akhirnya, kami memecahkan pemrosesan rekaman lebih lanjut dengan next .
Kondisi kedua hanya akan menargetkan catatan /etc/passwd , ketika bidang keempat $4 ( ID grup ) hadir dalam array $4 in g , kami akan mencetak login dan nilai yang ditunjuk oleh array yang diindeks oleh ID grup g[$4] , jadi: print $1""FS""g[$4] .
Contoh Output Utilitas Pengguna:
$ users
negan rick bart klashxx klashxx ironman ironman ironmanKami akan menghitung logon per pengguna.
$ users | awk ' {a[$1]++}
END{for (i in a){print i,a[i]}} ' RS= ' + '
rick 1
bart 1
ironman 3
negan 1
klashxx 2Tindakan dilakukan untuk semua catatan.
a[$1]++ : Ini adalah penghitung , untuk setiap pengguna $1 itu menambah nilai runcing (vars yang tidak diinisialisasi memiliki nilai numerik nol).
Di END blok mengulangi array dengan kunci dan nilai tersimpan untuk menyajikan hasil.
Output khas :
$ uptime
11:08:51 up 121 days, 13:09, 10 users, load average: 9.12, 14.85, 20.84Bagaimana kita bisa mendapatkan rata -rata rata -rata beban total?
$ uptime | awk ' {printf "Load average mean: %0.2fn",
($(NF-2)+$(NF-1)+$(NF))/3 } ' FS= ' (:|,) + '
Load average mean: 14.94Ini teknik baru.
Kami menggunakan [regex] sebagai pemisah lapangan (:|,) + , sehingga FS dapat menjadi usus besar dan koma diikuti oleh nol atau lebih ruang kosong.
Kami hanya membutuhkan tiga bidang terakhir untuk melakukan aritmatika yang diperlukan, maka kami menggunakan printf yang terpasang pada topeng yang tepat .
Jika Anda masih di sini, terima kasih !!
Dari sudut pandang saya, awk adalah bahasa yang diremehkan dan membutuhkan banyak cinta ❤️.
Jika Anda lapar untuk lebih banyak, beri tahu saya di bagian komentar di bawah dan saya akan mempertimbangkan bagian kedua untuk menyelesaikan misi saya ... membuat Anda mati sampai mati.
Happy Coding!
[Panduan untuk Mengutip Shell Unix] [Quoting-Guide]. ↩
[Wikipedia pada jaringan pipa] [PIPES]. ↩
Ada saat -saat ketika lebih mudah untuk memaksa awk untuk membangun kembali seluruh catatan, menggunakan nilai -nilai FS dan OFS saat ini.
Untuk melakukan ini, kami menggunakan penugasan yang tampaknya tidak berbahaya: $1 = $1 ↩ ↩ 2
Jawaban cepat, itu hanya jalan pintas yang harus dihindari menggunakan pernyataan cetak.
Dalam awk ketika suatu kondisi cocok dengan tindakan default adalah mencetak baris input.
$ echo "test" |awk '1'
Setara dengan:
echo "test"|awk '1==1'
echo "test"|awk '{if (1==1){print}}'
Itu karena 1 akan selalu [benar]. ↩