Mari kita lihat halaman manual awk GNU:
FS
— Pemisah kolom input, spasi secara default. Lihat Bidang , di atas.
Ke Bidang bagian!
Saat setiap catatan masukan dibaca, gawk membagi catatan menjadi beberapa bidang, menggunakan nilai
FS
variabel sebagai pemisah bidang. JikaFS
adalah karakter tunggal, bidang dipisahkan oleh karakter tersebut. JikaFS
adalah string nol, maka setiap karakter individu menjadi bidang yang terpisah. Jika tidak,FS
diharapkan menjadi ekspresi reguler penuh. Dalam kasus khusus yaituFS
adalah satu spasi, kolom dipisahkan oleh rangkaian spasi dan/atau tab dan/atau baris baru.
Inilah ringkasan pragmatis yang berlaku untuk semua penerapan Awk utama :
- GNU Awk (
gawk
) -awk
default di beberapa distro Linux - Mawk (
mawk
) -awk
default di beberapa Distro Linux (misalnya, versi Ubuntu sebelumnya) - BWK Awk -
awk
default pada platform mirip BSD, termasuk macOS
Versi terkini dari semua implementasi ini mengikuti standar POSIX sehubungan dengan bidang pemisah (namun bukan rekam pemisah).
Glosarium:
-
RS
adalah masukan-catatan pemisah , yang menjelaskan bagaimana masukan dipecah menjadi catatan :- Nilai default yang dimandatkan POSIX adalah baris baru , juga disebut sebagai
\n
di bawah; yaitu, masukan dipecah menjadi baris secara default . - Aktif
awk
baris perintah,RS
dapat ditentukan sebagai-v RS=<sep>
. - POSIX membatasi
RS
menjadi harfiah, karakter tunggal nilai, tetapi GNU Awk dan Mawk mendukung multi-karakter nilai yang mungkin merupakan ekspresi reguler yang diperluas (BWK Awk tidak dukung itu).
- Nilai default yang dimandatkan POSIX adalah baris baru , juga disebut sebagai
-
FS
adalah bidang input- pemisah , yang menjelaskan bagaimana setiap catatan dibagi menjadi bidang ; ini mungkin merupakan ekspresi reguler yang diperluas .- Aktif
awk
baris perintah,FS
dapat ditentukan sebagai-F <sep>
(atau-v FS=<sep>
). - Nilai default yang dimandatkan POSIX adalah secara formal sebuah ruang (
0x20
), tetapi ruang itu tidak secara harfiah diartikan sebagai (satu-satunya) pemisah, tetapi memiliki makna khusus ; lihat di bawah.
- Aktif
Secara default :
- lari apapun dari spasi dan/atau tab dan/atau baris baru diperlakukan sebagai pemisah kolom
- dengan perjalanan di depan dan di belakang diabaikan .
Perhatikan bahwa dengan pemisah rekaman masukan default (RS
), \n
, baris baru biasanya jangan masukkan gambar sebagai pemisah bidang , karena tidak ada catatan itu sendiri berisi \n
dalam hal itu.
Baris baru sebagai pemisah bidang lakukan ikut bermain , namun:
- Kapan
RS
disetel ke nilai yang menghasilkan rekaman sendiri berisi\n
contoh (seperti saatRS
disetel ke string kosong; lihat di bawah). - Umumnya , ketika
split()
fungsi digunakan untuk membagi string menjadi elemen larik tanpa argumen pemisah bidang eksplisit.- Meskipun masukan mencatat tidak akan berisi
\n
contoh jikaRS
default berlaku,split()
fungsi saat dipanggil tanpa argumen pemisah bidang eksplisit pada string multibaris dari sumber berbeda (mis., variabel diteruskan melalui-v
pilihan atau sebagai pseudo-filename) selalu memperlakukan\n
sebagai pemisah bidang.
- Meskipun masukan mencatat tidak akan berisi
Pertimbangan NON-default penting :
-
Menetapkan kosong string ke
RS
memiliki arti khusus :membaca input dalam mode paragraf , artinya input dipecah menjadi catatan oleh berjalannya baris tidak kosong , dengan garis kosong di depan dan di belakang diabaikan . -
Saat Anda menetapkan sesuatu lainnya daripada literal spasi ke
FS
, interpretasi dariFS
berubah secara fundamental :- Sebuah tunggal karakter atau setiap karakter dari karakter tertentu set diakui secara individual sebagai pemisah bidang - bukan berjalan itu, seperti dengan default.
- Misalnya, menyetel
FS
ke[ ]
- meskipun itu efektif berjumlah satu spasi - menyebabkan setiap individu instance space di setiap catatan untuk diperlakukan sebagai pemisah bidang. - Untuk mengenali berjalan , bilangan regex (simbol duplikasi)
+
harus digunakan; mis.,[\t]+
akan mengenali berjalan tab sebagai pemisah tunggal.
- Misalnya, menyetel
- Memimpin dan mengikuti pemisah TIDAK diabaikan , dan, sebagai gantinya, pisahkan kosong bidang.
- Menyetel
FS
ke string kosong artinya setiap karakter catatan adalah bidangnya sendiri .
- Sebuah tunggal karakter atau setiap karakter dari karakter tertentu set diakui secara individual sebagai pemisah bidang - bukan berjalan itu, seperti dengan default.
-
Seperti yang diamanatkan oleh POSIX, jika
RS
disetel ke string kosong (mode paragraf), baris baru (\n
) adalah juga dianggap pemisah bidang , terlepas dari nilaiFS
.
- Dengan
-P
berlaku danRS
setel ke string kosong ,\n
masih diperlakukan sebagai pemisah bidang:
gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
- Dengan
-P
berlaku dan tidak kosongRS
,\n
TIDAK diperlakukan sebagai pemisah bidang - ini adalah perilaku usang:
gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
Perbaikan akan datang , menurut pengelola GNU Awk; mengharapkannya dalam versi 4.2 (tidak ada kerangka waktu yang diberikan).
(Ujung topi untuk @JohnKugelman dan @EdMorton atas bantuan mereka.)
'[ ]+' berfungsi untuk saya. Jalankan awk -W version
untuk mendapatkan versi awk. Milik saya adalah GNU Awk 4.0.2
.
# cat a.txt
tcp 0 0 10.192.25.199:65002 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:26895 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:18422 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 10.192.25.199:8888 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:50010 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:50075 0.0.0.0:* LISTEN
tcp 0 0 10.192.25.199:8093 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:8670 0.0.0.0:* LISTEN
Misalnya, saya ingin mendapatkan port Listen. Jadi saya perlu menggunakan pembatas default awk yang ditambahkan dengan ':'
# cat a.txt | awk -F '[ ]+|:' '{print $5}'
65002
26895
111
18422
22
8888
50010
50075
8093
8670
Jika Anda hanya ingin menguji pembatas default, Anda dapat menjalankan
# cat a.txt | awk -F '[ ]+' '{print $4}'
10.192.25.199:65002
127.0.0.1:26895
0.0.0.0:111
0.0.0.0:18422
0.0.0.0:22
10.192.25.199:8888
0.0.0.0:50010
0.0.0.0:50075
10.192.25.199:8093
0.0.0.0:8670
Hasilnya seperti yang diharapkan.
Pertanyaan the default delimiter is only space for awk?
ambigu tetapi saya akan mencoba menjawab kedua pertanyaan yang mungkin Anda tanyakan.
Nilai default dari FS
variabel (yang menampung pemisah bidang yang memberi tahu awk cara memisahkan catatan ke dalam bidang saat dibaca) adalah karakter spasi tunggal.
Hal yang awk gunakan untuk memisahkan catatan ke dalam bidang adalah "pemisah bidang" yang merupakan ekspresi reguler dengan beberapa fungsi tambahan yang hanya berlaku jika pemisah bidang adalah satu karakter kosong. Fungsionalitas tambahan itu adalah:
- Spasi kosong di depan dan di belakang diabaikan selama pemisahan bidang.
- Kolom dipisahkan dalam rantai karakter spasi yang berdekatan yang mencakup kosong, tab, dan baris baru.
- Jika Anda ingin menggunakan karakter kosong literal sebagai pemisah bidang, Anda harus menentukannya sebagai
[ ]
alih-alih hanya char kosong literal mandiri seperti yang Anda bisa di regexp.
Selain pemisah bidang yang digunakan untuk membagi catatan menjadi bidang saat input dibaca, mereka digunakan dalam beberapa konteks lain, mis. arg ke-3 untuk split()
, jadi penting bagi Anda untuk mengetahui konteks mana yang memerlukan string atau regexp atau fieldsep dan halaman manual dengan jelas menentukan masing-masing.
Antara lain, hal di atas menjelaskan hal ini:
$ echo ' a b c ' | awk '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F' ' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F'[ ]' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
5: <> <a> <b>
jadi jika Anda tidak mengerti mengapa 2 yang pertama menghasilkan keluaran yang sama tetapi yang terakhir berbeda, tanyakan.