GNU/Linux >> Linux Esercitazione >  >> Linux

Separatore di campo predefinito per awk

Diamo un'occhiata alla pagina man di GNU awk:

FS — Il separatore del campo di input, uno spazio per impostazione predefinita. Vedi Campi , sopra.

Ai Campi sezione!

Man mano che ogni record di input viene letto, gawk suddivide il record in campi, utilizzando il valore di FS variabile come separatore di campo. Se FS è un singolo carattere, i campi sono separati da tale carattere. Se FS è la stringa nulla, quindi ogni singolo carattere diventa un campo separato. Altrimenti, FS dovrebbe essere un'espressione regolare completa. Nel caso speciale che FS è uno spazio singolo, i campi sono separati da sequenze di spazi e/o tabulazioni e/o newline.


Ecco un riassunto pragmatico questo si applica a tutte le principali implementazioni di Awk :

  • GNU Awk (gawk ) - il awk predefinito in alcuni distribuzioni Linux
  • Mawk (mawk ) - il awk predefinito in alcuni Distribuzioni Linux (ad es. versioni precedenti di Ubuntu )
  • BWK Awk - il awk predefinito su piattaforme simili a BSD, incluso macOS

Versioni recenti di tutte queste implementazioni seguono lo standard POSIX rispetto a field separatori (ma non registra separatori).

Glossario:

  • RS è il input-record separatore , che descrive come l'input viene suddiviso in record :

    • Il valore predefinito imposto da POSIX è una nuova riga , indicato anche come \n sotto; ovvero, l'input è suddiviso in righe per impostazione predefinita .
    • Su awk riga di comando di , RS può essere specificato come -v RS=<sep> .
    • POSIX limita RS a un letterale, a un solo carattere value, ma GNU Awk e Mawk supportano multi-carattere valori che possono essere espressioni regolari estese (BWK Awk non supportalo).
  • FS è il campo di input separatore , che descrive come ogni record è suddiviso in campi ; potrebbe essere un'espressione regolare estesa .

    • Su awk riga di comando di , FS può essere specificato come -F <sep> (o -v FS=<sep> ).
    • Il valore predefinito imposto da POSIX è formalmente uno spazio (0x20 ), ma quello spazio non è letteralmente interpretato come (l'unico) separatore, ma ha un significato speciale ; vedi sotto.

Per impostazione predefinita :

  • qualsiasi esecuzione di spazi e/o schede e/o newline viene trattato come un separatore di campo
  • con sequenze iniziali e finali ignorate .

Tieni presente che con il separatore di record di input predefinito (RS ), \n , newline tipicamente non inserire l'immagine come separatore di campo , perché nessun record stesso contiene \n in tal caso.

Le nuove righe come separatori di campo fare entrano in gioco , tuttavia:

  • Quando RS è impostato su un valore che genera i record stessi contenente \n istanze (come quando RS è impostato sulla stringa vuota; vedi sotto).
  • Generalmente , quando split() La funzione viene utilizzata per suddividere una stringa in elementi dell'array senza un argomento separatore di campo esplicito.
    • Anche se i record di input non conterrà \n istanze nel caso in cui il valore predefinito RS è in vigore, il split() funzione quando viene richiamata senza un argomento separatore di campo esplicito su una stringa multilinea da una fonte diversa (ad esempio, una variabile passata tramite il -v opzione o come pseudo-nome file) sempre tratta \n come separatore di campo.

Considerazioni importanti NON predefinite :

  • Assegnazione del vuoto stringa a RS ha un significato speciale :legge l'input in modalità paragrafo , il che significa che l'input viene suddiviso in record mediante sequenze di righe non vuote , con sequenze iniziali e finali di righe vuote ignorate .

  • Quando assegni qualcosa other piuttosto che un letterale spazio a FS , l'interpretazione di FS cambia radicalmente :

    • Un singolo carattere o ogni carattere da un set di caratteri specificato è riconosciuto individualmente come separatore di campo - non funziona di esso, come con il default.
      • Ad esempio, impostando FS a [ ] - anche se efficacemente equivale a un singolo spazio - causa ogni individuo istanza di spazio in ogni record da trattare come separatore di campo.
      • Per riconoscere le corse , il quantificatore regex (simbolo di duplicazione) + deve essere usato; ad esempio, [\t]+ riconoscerebbe le corse di schede come separatore singolo.
    • In testa e in coda i separatori NON vengono ignorati e, invece, separato vuoto campi.
    • Impostazione FS alla stringa vuota significa che ogni carattere di un record è il proprio campo .
  • Come richiesto da POSIX, se RS è impostato sulla stringa vuota (modalità paragrafo), newline (\n ) sono anche considerati separatori di campo , indipendentemente dal valore di FS .

  • Con -P in vigore e RS impostato sulla stringa vuota , \n è ancora trattato come un separatore di campo:
    gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
  • Con -P in vigore e un non vuoto RS , \n NON viene trattato come un separatore di campo - questo è il comportamento obsoleto:
    gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
    È in arrivo una correzione , secondo i manutentori di GNU Awk; aspettalo nella versione 4.2 (nessun periodo di tempo indicato).
    (Suggerimento del cappello a @JohnKugelman e @EdMorton per il loro aiuto.)

'[ ]+' funziona per me. Esegui awk -W version per ottenere la versione awk. Il mio è 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

Ad esempio, voglio ottenere la porta di ascolto. Quindi ho bisogno di usare il delimitatore predefinito awk aggiunto con ':'

# cat a.txt  | awk -F '[ ]+|:' '{print $5}'
65002
26895
111
18422
22
8888
50010
50075
8093
8670

Se vuoi solo testare il delimitatore predefinito, puoi eseguire

# 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

Il risultato è come previsto.


La domanda the default delimiter is only space for awk? è ambiguo, ma cercherò di rispondere a entrambe le domande che potresti porre.

Il valore predefinito di FS variabile (che contiene il separatore di campo che dice ad awk come separare i record nei campi mentre li legge) è un singolo carattere di spazio.

La cosa che awk usa per separare i record in campi è un "separatore di campo" che è un'espressione regolare con alcune funzionalità aggiuntive che si applicano solo quando il separatore di campo è un singolo carattere vuoto. Quella funzionalità aggiuntiva è che:

  1. Gli spazi bianchi iniziali e finali vengono ignorati durante la divisione del campo.
  2. I campi sono separati da catene di spazi contigui che includono spazi vuoti, tabulazioni e nuove righe.
  3. Se desideri utilizzare un carattere vuoto letterale come separatore di campo, devi specificarlo come [ ] invece di solo un carattere vuoto letterale autonomo come potresti fare in una regexp.

Oltre ai separatori di campo utilizzati per suddividere i record in campi durante la lettura dell'input, vengono utilizzati in altri contesti, ad es. il 3° argomento per split() , quindi è importante sapere quali contesti richiedono una stringa o una regexp o un fieldsep e la pagina man specifica chiaramente ciascuno di essi.

Tra le altre cose, quanto sopra spiega questo:

$ 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>

quindi se non capisci perché i primi 2 producono lo stesso output ma l'ultimo è diverso, chiedi pure.


Linux
  1. Come impostare le opzioni di montaggio automatico predefinite per i supporti rimovibili?

  2. Preso nel giro? Awk While, Do While, For Loop, Break, Continue, Exit Esempi

  3. 9 potenti funzioni integrate di Awk per i numeri

  4. Come aggiungere un percorso di inclusione predefinito per GCC in Linux?

  5. Qual è la password di root predefinita per MySQL 5.7

5 migliori lanciatori di applicazioni per Ubuntu

Modificare la shell predefinita per Terminator?

Tutorial Regex per esempi di Linux (Sed e AWK).

migliore utilità di esplorazione grafica dello spazio su disco per Ubuntu?

grep per termine ed escludi un altro termine

Come impostare l'umask predefinito per il servlet webdav di Tomcat?