Utilizzo di più delimitatori in awk


202

Ho un file che contiene le seguenti righe:

/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

Nell'output sopra voglio estrarre 3 campi (numero 2, 4 e l'ultimo *.example.com). Sto ottenendo il seguente output:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

Come estrarre anche l'ultimo campo con il nome di dominio che è dopo '='? Come si usa multiple delimiterper estrarre il campo?


2
Per rispondere alla mia domanda che è la stessa cosa ma diversa, è awkstato ingoiare i campi quando erano vuoti, il che ha ostacolato la numerazione dei campi. Ho cambiato -F " "per -F "[ ]"e awknon ingoiare più i campi vuoti.
Adam,

Risposte:


324

Il delimitatore può essere un'espressione regolare.

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

produce:

tc0001   tomcat7.1    demo.example.com  
tc0001   tomcat7.2    quest.example.com  
tc0001   tomcat7.5    www.example.com

42
Naturalmente, catnon è necessario processo: awk '...' file. Inoltre, sarebbe più ordinato utilizzare il separatore del campo di output:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
glenn jackman,

17
I delimitatori Awk possono essere espressioni regolari ... questo ha reso la mia giornata!
das.cyklone,

4
@ das.cyklone: ​​awk può anche avere diversi separatori, con |: ex: awk -F 'this|that|[=/]' '......' (utile per avere parole / stringhe che separano le cose) (nota che questo mantiene gli spazi tra i separatori tra i 2 separatori. L'aggiunta |[ \t]+può anche essere utile, ma può rendere le cose difficile ... dato che spesso ci sono spazi prima e dopo "questo", questo farà apparire 2 campi extra vuoti tra lo spazio (i) e "questo")
Olivier Dulac,

Ho provato questo su 2 distro diverse e ho lo stesso comportamento: voglio ottenere la porta da netstat -ntpl "netstat -ntpl | sed 's /: / /' | awk '{print $ 5}'" funziona ma potrei fare a meno del doulbe piping Funziona ma non mi aspettavo i dati sul campo 17: "netstat -ntpl | awk -F" |: "'{print $ 17}'"
louigi600

2
sì ... questo mi ha ottenuto quello che volevo: awk -F "[:] +" '/ \ / postmaster * $ / {print $ 5}'
louigi600

44

Buone notizie! awkil separatore di campo può essere un'espressione regolare. Devi solo usare -F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

Ritorna:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

Qui:

  • -F"/|="imposta il separatore del campo di input su /o =. Quindi imposta il separatore del campo di output su una scheda.

  • -vOFS='\t'sta usando il -vflag per impostare una variabile. OFSè la variabile predefinita per il separatore del campo di output ed è impostata sul carattere di tabulazione. La bandiera è necessaria perché non esiste un built-in per l'OFS -F.

  • {print $3, $5, $NF} stampa il 3 °, 5 ° e ultimo campo in base al separatore del campo di input.


Vedi un altro esempio:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

Questo file ha due campi separatori #e _. Se vogliamo stampare il secondo campo indipendentemente dal fatto che il separatore sia l'uno o l'altro, facciamo in modo che entrambi siano separatori!

$ awk -F"#|_" '{print $2}' file
how
am

Dove i file sono numerati come segue:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
  1    2   3   4            1  2   3    4    5    6

1
Grazie @BUFU per la modifica. Ho rimosso il riferimento OFS per concentrarmi solo sulla parte FS, ma è anche bello averlo. Saluti!
fedorqui "SO smettere di danneggiare"

5

Se lo spazio bianco è coerente, è possibile utilizzarlo come delimitatore, inoltre invece di inserire \tdirettamente, è possibile impostare il separatore di output e verrà incluso automaticamente:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'

3

Per un separatore di campo di qualsiasi numero 2attraverso 5o lettera ao #o uno spazio, in cui il carattere di separazione deve essere ripetuto almeno 2 volte e non più di 6 volte, ad esempio:

awk -F'[2-5a# ]{2,6}' ...

Sono sicuro che esistono variazioni di questo usando () e parametri


3

Perl one-liner:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

Vengono utilizzate queste opzioni della riga di comando:

  • -n$_eseguire il ciclo attorno a ogni riga del file di input, inserire la riga nella variabile, non stampare automaticamente ogni riga

  • -l rimuove le nuove righe prima dell'elaborazione e le aggiunge nuovamente in seguito

  • -amodalità autosplit - perl divide automaticamente le linee di input @Fnell'array. L'impostazione predefinita è la divisione in spazi bianchi

  • -Fmodificatore autosplit, in questo esempio si divide su /o=

  • -e eseguire il codice perl

Perl è strettamente correlato a awk, tuttavia, l' @Farray autosplit inizia all'indice $F[0]mentre i campi awk iniziano con $ 1.


2

Un altro è usare l'opzione -F ma passarla regex per stampare il testo tra parentesi sinistra o destra ().

Il contenuto del file:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

Il comando:

awk -F"[()]" '{print $2}' filename

risultato:

smbw
smbt
smbn
smbs

Usare awk per stampare il testo tra []:

Usa awk -F'[][]' ma awk -F'[[]]'non funzionerà.

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html


La tua risposta è arrivata nella coda di eliminazione perché 9 volte su 10, gli utenti con 1 reputazione che si collegano al proprio blog di solito sono spam. Ma la tua è l'eccezione alla regola. Negli ultimi 10 anni di contenuti c'è una miniera d'oro, speriamo che tu abbia un piano per immortalarlo.
Eric Leschinski il

0

Vedo che sulla lavagna sono presenti molte risposte perfette, ma vorrei comunque caricare anche il mio codice,

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'


2
print $3 " " $5 " " $7può essere stampato come print $3, $5, $7. Inoltre, non vedo il vantaggio di usare awk e quindi eseguire il piping su sed. In generale, awk può bastare e altri rispondono dimostrarlo.
fedorqui "SO smettere di danneggiare" il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.