Podívejme se na manuálovou stránku GNU awk:
FS
— Oddělovač vstupního pole, ve výchozím nastavení mezera. Viz Pole , výše.
Na Pole sekce!
Když je každý vstupní záznam načten, gawk rozdělí záznam do polí pomocí hodnoty
FS
proměnná jako oddělovač pole. PokudFS
je jeden znak, pole jsou oddělena tímto znakem. PokudFS
je nulový řetězec, pak se každý jednotlivý znak stane samostatným polem. JinakFS
očekává se, že bude úplný regulární výraz. Ve speciálním případě, žeFS
je jedna mezera, pole jsou oddělena řadou mezer a/nebo tabulátorů a/nebo nových řádků.
Zde je pragmatické shrnutí to platí pro všechny hlavní implementace Awk :
- GNU Awk (
gawk
) – výchozíawk
v některých Linuxové distribuce - Mawk (
mawk
) – výchozíawk
v některých Linuxové distribuce (např. starší verze Ubuntu) - BWK Awk – výchozí
awk
na platformách podobných BSD, včetně macOS
Poslední verze všech tyto implementace se řídí standardem POSIX s ohledem na pole oddělovače (ale ne záznam oddělovače).
Glosář:
-
RS
je vstup-záznam oddělovač , která popisuje, jak je vstup rozdělen do záznamů :- Výchozí hodnota nařízená POSIX je nový řádek , také označovaný jako
\n
níže; to znamená, že vstup je rozdělen do řádků ve výchozím nastavení . - Na
awk
's příkazový řádek,RS
lze zadat jako-v RS=<sep>
. - POSIX omezuje
RS
na doslovný, jednoznakový hodnotu, ale GNU Awk a Mawk podporují víceznakové hodnoty, které mohou být rozšířenými regulárními výrazy (BWK Awk nedělá podporujte to).
- Výchozí hodnota nařízená POSIX je nový řádek , také označovaný jako
-
FS
je vstupní-pole oddělovač , která popisuje, jak každý záznam je rozdělena do polí ; může to být rozšířený regulární výraz .- Na
awk
's příkazový řádek,FS
lze zadat jako-F <sep>
(nebo-v FS=<sep>
). - Výchozí hodnota nařízená standardem POSIX je formálně mezera (
0x20
), ale tento prostor není doslova interpretován jako (jediný) oddělovač, ale má zvláštní význam ; viz níže.
- Na
Ve výchozím nastavení :
- jakýkoli běh z mezer a/nebo karty a/nebo nové řádky je považováno za oddělovač polí
- s ignorováním úvodních a koncových běhů .
Všimněte si, že s výchozím oddělovačem vstupního záznamu (RS
), \n
, nové řádky obvykle nevkládejte obrázek jako oddělovače polí , protože žádný záznam samotný obsahuje \n
v tom případě.
Nové řádky jako oddělovače polí dělají vstoupit do hry , nicméně:
- Když
RS
je nastavena na hodnotu, která vede k samotným záznamům obsahující\n
instance (například kdyžRS
je nastaven na prázdný řetězec; viz níže). - Obecně , když
split()
Funkce se používá k rozdělení řetězce na prvky pole bez argumentu oddělovače explicitních polí.- I když vstupní záznamy nebude obsahovat
\n
instance v případě, že výchozíRS
platí,split()
funkce při vyvolání bez explicitního argumentu oddělovače polí na víceřádkovém řetězci z jiného zdroje (např. proměnná předaná prostřednictvím-v
možnost nebo jako pseudonázev souboru) vždy zpracovává\n
jako oddělovač polí.
- I když vstupní záznamy nebude obsahovat
Důležité informace, které nejsou výchozí :
-
Přiřazení prázdného řetězec na
RS
má zvláštní význam :čte vstup v režimu odstavce , což znamená, že vstup je rozdělen do záznamů podle běhů neprázdných řádků , přičemž začátek a konec prázdných řádků jsou ignorovány . -
Když přiřadíte cokoli jiného než doslov mezera na
FS
, interpretaceFS
zásadně se mění :- A single znak nebo každý znak ze zadané znakové sady je uznáván individuálně jako oddělovač polí - ne běží stejně jako u výchozího nastavení.
- Například nastavení
FS
na[ ]
- i když to efektivně se rovná jedné mezerě – způsobuje každý jednotlivec instance prostoru v každém záznamu, která má být považována za oddělovač polí. - Pro rozpoznání běhů , kvantifikátor regulárního výrazu (symbol duplikace)
+
musí být použit; např.[\t]+
rozpozná běhy tabulátorů jako jeden oddělovač.
- Například nastavení
- Přední a koncové oddělovače NEJSOU ignorovány a místo toho oddělte prázdné pole.
- Nastavení
FS
na prázdný řetězec znamená, že každý znak záznamu je jeho vlastní pole .
- A single znak nebo každý znak ze zadané znakové sady je uznáván individuálně jako oddělovač polí - ne běží stejně jako u výchozího nastavení.
-
Podle nařízení POSIX, pokud
RS
je nastaven na prázdný řetězec (režim odstavce), nové řádky (\n
) jsou také považovány za oddělovače polí , bez ohledu na hodnotuFS
.
- S
-P
v platnosti aRS
nastavte na prázdný řetězec ,\n
je stále považováno za oddělovač pole:
gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
- S
-P
v platnosti a neprázdnéRS
,\n
NENÍ považováno za oddělovač polí – toto je zastaralé chování:
gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
Přichází oprava , podle správců GNU Awk; očekávejte to ve verzi 4.2 (není uveden časový rámec).
(Hrot klobouku @JohnKugelman a @EdMorton za jejich pomoc.)
'[ ]+' mi funguje. Spusťte awk -W version
získat verzi awk. Můj je 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
Například chci získat port Listen. Takže musím použít výchozí oddělovač awk přidaný s ':'
# cat a.txt | awk -F '[ ]+|:' '{print $5}'
65002
26895
111
18422
22
8888
50010
50075
8093
8670
Pokud chcete pouze otestovat výchozí oddělovač, můžete spustit
# 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
Výsledek je podle očekávání.
Otázka the default delimiter is only space for awk?
je nejednoznačný, ale pokusím se odpovědět na obě otázky, na které se možná ptáte.
Výchozí hodnota FS
proměnná (která obsahuje oddělovač polí, který awk říká, jak rozdělit záznamy do polí při jejich čtení) je jedna mezera.
Věc, kterou awk používá k oddělení záznamů do polí, je "oddělovač polí", což je regulární výraz s některými dalšími funkcemi, které se používají pouze v případě, že oddělovačem polí je jeden prázdný znak. Tato další funkce je následující:
- Během rozdělování polí jsou ignorovány úvodní a koncové mezery.
- Pole jsou oddělena řetězci souvislých mezer, které zahrnují mezery, tabulátory a nové řádky.
- Pokud chcete jako oddělovač polí použít doslovný prázdný znak, musíte jej zadat jako
[ ]
namísto pouhého samostatného doslovného prázdného znaku, jako byste mohli v regulárním výrazu.
Kromě oddělovačů polí, které se používají k rozdělení záznamů do polí při čtení vstupu, se používají v některých jiných kontextech, např. 3. argument pro split()
, takže je důležité, abyste věděli, které kontexty vyžadují řetězec nebo regulární výraz nebo fieldep a manuálová stránka každý z nich jasně specifikuje.
Výše uvedené mimo jiné vysvětluje toto:
$ 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>
takže pokud nerozumíte tomu, proč první 2 produkují stejný výstup, ale poslední je jiný, zeptejte se.