2011-09-11 13 views
5

Ho bisogno di cancellare una riga corrispondente e una precedente. ad esempio Nel file seguente devo rimuovere le righe 1 & 2.Come si elimina una riga corrispondente e la precedente?

Ho provato la pagina "grep -v -B 1". di. "1.txt e mi aspettavo che non stampa le linee matchning e il contesto.

Ho provato il How do I delete a matching line, the line above and the one below it, using sed?, ma non riuscivo a capire l'uso sed.

---1.txt-- 
**document 1**       -> 1 
**page 1 of 2**      -> 2 

testoing 
testing 

super crap blah 

**document 1** 
**page 2 of 2** 
+2

prova [ 'file di tac | sed -e '/ foo /, + 1d' | tac'] (http://stackoverflow.com/a/31227307/2297751) – Jon

risposta

1

Non troppo familiarità con sed, ma ecco un'espressione perl per fare il trucco:

cat FILE | perl -e '@a = <STDIN>; 
        for($i=0 ; $i <= $#a ; $i++) { 
        if($i > 0 && $a[$i] =~ /xxxx/) { 
         $a[$i] = ""; 
         $a[$i-1] = ""; 
        } 
        } print @a;' 

edit:

dove "xxxx" è ciò che stai cercando di abbinare.

+0

questo deve prima bufferizzare l'intero file ... –

+0

E l'uso inutile di Cat dovrebbe andare. – tripleee

+0

Sì, alcuni pezzi di questa soluzione possono essere criticati, ma il concetto generale è solido e il codice di esempio lo implementa abbastanza bene. È facile da capire Basta per far iniziare qualcuno. E questo è il punto centrale di una risposta qui. Non ha bisogno di essere perfetto. Mi piace questa risposta. Mi ha sicuramente aiutato con un problema simile alla domanda originale. – Keve

11

si vuole fare qualcosa di molto simile alla answer given

sed -n ' 
/page . of ./ { #when pattern matches 
n #read the next line into the pattern space 
x #exchange the pattern and hold space 
d #skip the current contents of the pattern space (previous line) 
} 

x #for each line, exchange the pattern and hold space 
1d #skip the first line 
p #and print the contents of pattern space (previous line) 

$ { #on the last line 
x #exchange pattern and hold, pattern now contains last line read 
p #and print that 
}' 

E come una singola linea di

sed -n '/page . of ./{n;x;d;};x;1d;p;${x;p;}' 1.txt 
+0

Si noti che è possibile farlo su una riga: 'sed -n '/ pagina 1/{n; x; d;}; x; 1d; $ G; p' 1.txt' – Beta

+0

@Beta: Naturalmente, il linee extra, ecc. sono solo annotazioni – Hasturkun

+1

Perché è stato downvoted? fa quello che voleva il richiedente la domanda (ed è in sed per avviarsi) – Hasturkun

2

grep -v -B1 non funziona perché salterà quelle linee, ma includerà loro in seguito (a causa . al -B1 di controllare questo fuori, provate il comando su:

**document 1**       -> 1 
**page 1 of 2**      -> 2 

**document 1** 
**page 2 of 2** 
**page 3 of 2** 

Si noterà che la linea page 2 verrà saltata perché quella linea non verrà abbinata e quella successiva non sarà abbinata.

C'è una soluzione semplice awk:

awk '!/page.*of.*/ { if (m) print buf; buf=$0; m=1} /page.*of.*/ {m=0}' 1.txt 

Il comando awk dice il seguente:

Se la linea attuale ha che "... la pagina di", allora sarà il segnale che si rifugio' Ho trovato una linea valida. Se non trovate quella stringa, quindi si stampa la riga precedente (memorizzato in buf) e reimposta il buffer per la linea corrente (da qui costringendolo ad essere in ritardo da 1)

1
grep -vf <(grep -B1 "page.*of" file | sed '/^--$/d') file 
+0

Si vuole aggiungere l'opzione '-x' al' grep' esterno. Questo non è terribilmente efficiente. – tripleee

Problemi correlati