Come tagliare senza buffer?


8

Voglio ottenere solo gli indirizzi e-mail che terminano in "@ xyz.nl" dal mio file di registro della posta. Per raggiungere questo obiettivo faccio:

# tail -f /var/log/mail.log | grep --i --line-buffered "@xyz.nl" | cut -d '@' -f 1 | cut -d '<' -f 2

--Line-buffered with grep è necessario perché altrimenti bufferizzerà il suo output perché il pipe non è considerato un terminale. Grep produrrà linee come queste:

Aug 29 11:56:01 localhost postfix/smtp[4124]: 05491500123: to=<someone@xyz.nl>, relay=123.456.123.456[123.456.123.456]:25, delay=2, delays=0.4/0/0.4/1.2, dsn=2.0.0, status=sent (250 2.0.0 u7T9twxN074009 Message accepted for delivery)

Il primo taglio quindi effettua:

Aug 29 11:56:01 localhost postfix/smtp[4124]: 05491500123: to=<someone

Il secondo taglio dovrebbe generare:

someone

Tuttavia, sembra che anche il taglio sia buffering. Se avvio il comando con cat anziché tail -f ottengo tutti i risultati rilevanti (nel formato preferito) dal file di registro. Ma ho bisogno dei risultati dal file di registro in tempo reale.

Ho provato a usare unbuffer per questo:

# tail -f /var/log/mail.log | grep --i --line-buffered "@xyz.nl" | unbuffer cut -d '@' -f 1 | cut -d '<' -f 2

Ho anche provato:

# unbuffer tail -f /var/log/mail.log | grep --i --line-buffered "@xyz.nl" | unbuffer cut -d '@' -f 1 | cut -d '<' -f 2

... che dovrebbe rimuovere il buffering 4K dal primo taglio . Tuttavia, questo non funziona. So che è il buffering perché se eseguo grep per il nostro dominio locale ottiene molti più hit, il buffer viene riempito prima e l'output viene generato prima (in batch 4K).

Quindi la mia domanda è: come taglio senza buffer ?

Correlati: So che sed e (g) awk possono fornirmi gli indirizzi e-mail. Ci ho provato ma non ho ancora ottenuto alcun risultato. Le risposte che usano sed o (g) awk sono benvenute e possono risolvere il mio problema diretto, ma rimango interessato alla risposta nominale della domanda su come annullare il buffering del comando cut. Il comando cut non parla di (un) buffering.


awk -F'[><@]' '/@xyz.nl/ {print $2}'...
jasonwryan,

1
prova grep -oP '[^<]+(?=@xyz.nl)'(insieme alle altre opzioni grep se necessario)
Sundeep

Entrambe le opzioni di awk e grep sopra funzionano come un fascino!
Forkbeard,

Risposte:


16

Se utilizzi un sistema GNU Coreutils (quasi qualsiasi Linux), puoi provare stdbuf:

… | stdbuf -oL cut -d '@' -f 1 | …

-oL rende il buffer di linea, che sembra quello che vuoi.


Questo è esattamente quello che stavo cercando, grazie!
Forkbeard,

Non cambia nulla per me per qualche motivo. :(
panzi

1
@panzi Sentiti libero di porre la tua domanda, collegandoti a questa. Per favore, includi tutti i dettagli (comando esatto che stai eseguendo, sistema operativo, distribuzione e versione, ecc.) Speriamo che qualcuno sia in grado di capire perché non funziona per te.
derobert,
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.