Come tagliare la parte dal file di registro?


18

Ho un file di registro da 8 GB (registro di produzione Rails). Devo tagliarlo tra alcune date (righe). Quale comando posso usare per fare questo?


1
Ehi ragazzi, questa domanda riguarda un file di grandi dimensioni, quindi è "Ante up!" .. il tempo conta ... Ho testato lo script sed preferito su un vero file da 8 GB, con 85904064 righe (100 caratteri per riga). Adoro sed, ma così com'è, lo script sed esegue la scansione dell'intero file, ogni volta. Questo lo rende in media due volte più lento dello script awk che esce-quando-trovato ... Penso (?) Lo script sed potrebbe aver bisogno solo di aq invece di d per la seconda espressione ... I risultati del test sono qui: incolla .ubuntu.com / 573477 .. Inoltre, non produce l'output corretto .. vedere il mio commento alla fine della risposta di asoundmove.
Peter

La nuova versione sed di asoundmove aveva affrontato il problema della velocità e ora corrisponde alla velocità di awks. e il nuovo versin ora genera correttamente i dati ... vedere i suoi commenti per maggiori dettagli.
Peter

Ho appena notato che hai detto "tagliare" (che in genere significa rimuovere) ... Intendi davvero "tagliare" o intendi "copia"? .... Se volevi dire "tagliare", allora sedlo farà facilmente.
Peter

Risposte:


12

Qualcosa di simile a

sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less

tee cut-logti permette di vedere sullo schermo cosa viene messo in archivio cut-log.

MODIFICARE:

Per soddisfare i rigorosi standard di fred.bear, ecco una soluzione sed (anche se probabilmente la soluzione awk è molto più carina):

b=BB; e=EE ;echo -e "AA\nAA\nBB\nBB\nCC\nCC\nDD\nDD\nEE\nEE\nFF\nFF" | sed -n ":b;/$b/b p;n;b b;:p;p;n;/$e/b e;b p;:e;p;n;/$e/b e;q"


3
@dogbane: sì, sì. Modificato. Sono sicuro che a volte scrivi meno di un codice ottimale, merita un commento così duro?
asoundmove,

1
nota: se ci sono più righe consecutive di "prima data" con la stessa data, tutte tranne la prima non verranno eliminate e verranno introdotte nell'output ... solo qualcosa di cui tenere conto ... (dipende da la situazione)
Peter

1
... ma, sebbene io sia un pro-sed ++, penso che questo particolare lavoro sia oltre i suoi limiti, per qualsiasi cosa diversa da un 'proprio strumento personale .. Ecco il problema principale che sed ha in questo caso (il tuo, e il mio .. sono riuscito a convincere sed a fare lo stesso del tuo .. funzionava anche nell'1%) .. di nuovo al problema principale .. (che non si applica a awk) .... Bug (non risolvibile): Per quanto riguarda una data che è valida nell'ambito del registro, ma che in realtà non è presente nel registro, nel caso del 1 ° argomento, sed non stampa nulla e, nel caso del 2 ° argomento, viene stampato tutto dopo il primo appuntamento! ... altro ...
Peter.O

1
Un altro bug risolvibile: è che attualmente abbina le date in qualsiasi riga, inclusa la protezione dei dati, ma è solo una modifica regex .. E per chiunque voglia usarlo, forse potresti commentare che gli arg ora si riferiscono al primo e ultime date nell'intervallo (non -1 e +1) .. e infine .. i miei "standard rigorosi" non sono i miei. Io sono solo il messaggero della richiesta Inquisitori ... L'utente si accorge se funziona come richiesto, o no .. Questa è stata una grande domanda per me .. Ho imparato molto :) ... e sono contento sapere che sedpuò corrispondere awkper la velocità, ed è stato in realtà un po 'più veloce.
Peter

6

Per stampare tutto tra FOO e BAR compreso, provare:

$ sed -n '/FOO/,/BAR/p' file.txt

1
nota: questo stamperà solo il primo BAR di una serie di BAR consecutivi ...
Peter.O

un'altra nota ... Un grosso problema se una delle date non è presente nei dati. Se l'ultima data non è presente, sed continuerà a emettere linee fino a raggiungere EOF.
Peter

5

Questo farà ciò che vuoi ...
Vengono visualizzate sia le date dei parametri Inclusa che Esclusa.

# set Test args
set  2011-02-24  2011-02-26  "junk"

from="$1"
till="$2"
file="$3"

# EITHER ====                              +++++++++  
# Ouptut lines between two parameter dates INCLUDING the parameter dates
  awk -v from=$from -v till=$till '
    ($2 >= from) && ($2 <= till) { print $0 ; next }
    ($2 > till) { exit }' "$file"

# OR ========                              ---------
# Ouptut lines between two parameter dates EXCLUDING the parameter dates
  awk -v from=$from -v till=$till '
    ($2 > from) && ($2 < till) { print $0 ; next }
    ($2 >= till) { exit }' "$file"

Verifica una data (ordinata) nel campo 2 ... Ecco un esempio dei dati del test

    98  2011-02-05 xxxx
    99  2011-02-05 xxxx
   100  2011-02-06 xxxx
   101  2011-02-06 xxxx

Ed ecco il generatore di dati di test .


Lo scriverei (prendendo il primo per esempio) un po 'più semplicemente così: awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
asoundmove,

@asoundmove: Sì, potrebbe sembrare migliore, ed è sicuramente più convenzionale , ma in realtà, il suo tempo di esecuzione è solo la durata di 1 ifistruzione aggiuntiva in totale (nemmeno 1 per riga). il flusso logico è effettivamente lo stesso e la differenza nel tempo di esecuzione verrebbe contata in nanosecondi .... L'unica ragione per cui non ho usato "altro" è che questo è effettivamente il mio primo awkscript in assoluto (a parte un giorno 4 anni fa quando ho suonato con alcuni esempi) ... e questo è il primo meccanismo di diramazione praticabile che ho trovato ... (e come detto. è altrettanto veloce) .. Generalmente uso sedTryq
Peter.O

Non capisco dove dai il nome e la posizione del file di testo in questo metodo? qualcuno può aiutarmi a vedere attraverso la mia stupidità
Giles,

4

Se nel tuo file di registro hai le date in questo formato YYYY-MM-DD, quindi, per trovare tutte le voci per dire, 2011-02-10, puoi fare:

grep 2011-02-10 log_file

Ora, diciamo, se si desidera trovare le voci per il 2011-02-10 e il 2011-02-11, utilizzare nuovamente grepma con più schemi:

grep -E '2011-02-10|2011-02-11' log_file

Buona. Funziona "come pubblicizzato" :) ... Tuttavia, grepcercherà l'intero file, anche se l' intervallo di date è all'inizio del file. In media questo raddoppia il tempo di una ricerca, rispetto a "exit-after-last-item-in-range" ... Mi sto solo preoccupando di menzionarlo a causa delle dimensioni del file da 8 GB menzionate nella domanda, Your i risultati del tempo grep sono quasi identici all'esempio sed qui (1 minuto e 58 secondi). Ecco il link ai risultati dei miei test cronometrati
Peter.O

1

Lavorare con questa dimensione di file è sempre difficile.

Un modo per andare avanti potrebbe essere quello di dividere questo file in un paio di piccoli, per fare ciò è possibile usare il comando split.

split -d -l 50000 ToBigFile.data file_

Anche se è diviso puoi sempre lavorare con il file come se fosse uno usando un bash per il ciclo

for f in `ls file_*`; do cat $f; done;

Ma invece del gatto puoi usare grep invertito per sbarazzarti di dati indesiderati, questo è irrilevante per questo. (o il tipo di raffinatezza di cui hai bisogno).

A questo punto lavorerai solo con molti file più piccoli, e i comandi che gli altri menzionati sopra lavoreranno su molti file più piccoli.

E quando hai finito, puoi usare un secondo ciclo per creare nuovamente il nuovo file più piccolo.

for f in `ls file_*`; do cat $f >> NewFile.data ; done;

Aggiornamento Dal momento che iniziamo a dividere i dati in più file, ci sarà molto lavoro con l'hard disk e ci vorrà del tempo. (In questa domanda apparentemente 5min).

D'altra parte i passi successivi sarebbero probabilmente più veloci.

Quindi questo metodo è probabilmente inutile per semplici operazioni grep, awk, sed, ma se i modelli di ricerca diventano più complicati, potrebbero diventare più veloci.


3
Johanm, ci vuole awk e sed solo 1 minuto, in media, per cercare un file di registro da 8 GB sul mio computer, e sullo stesso computer, solo la divisione iniziale dei file, richiede 4 minuti e 43 secondi ... :)
Peter.O

Diciamo che potresti ridurre i tempi di awk e sed del 50% sui file più piccoli. Quindi dobbiamo ancora fare più di 10 di queste operazioni prima di guadagnare sul tempo totale ... Quindi forse la suddivisione dei file non è la migliore idea per alcune regressioni ...
Johan

Lo script awk potrebbe (facilmente) essere modificato in modo da produrre 10 risultati di ricerca diversi in 10 file ... in un solo passaggio, ma ciò rallenterebbe la lettura durante l'output dei rapporti ... Anche Sed potrebbe fare lo stesso, ma ho menzionato nei commenti di asoundmove, sed fallirà se una data / ora particolare non ha alcuna voce nel registro (ad esempio, stai cercando a ore) .. Uso sed molto ed è estremamente utile, ma ha i suoi limiti ... Ecco una FAQ di sed su quando usare sed vs awk .. Non sono necessariamente d'accordo con tutto ciò, ma posso vedere cosa significano ... sed.sourceforge.net/sedfaq6.html
Peter. O

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.