don potrebbe essere migliore nella maggior parte dei casi, ma nel caso in cui il file sia davvero grande e non riesci seda gestire un file di script così grande (che può accadere a circa 5000+ righe di script) , eccolo qui sed:
sed -ne:t -e"/\n.*$match/D" \
-e'$!N;//D;/'"$match/{" \
-e"s/\n/&/$A;t" \
-e'$q;bt' -e\} \
-e's/\n/&/'"$B;tP" \
-e'$!bt' -e:P -e'P;D'
Questo è un esempio di quella che viene chiamata una finestra scorrevole sull'input. Funziona costruendo un buffer look-$B forward di -count prima di tentare di stampare qualsiasi cosa.
E in realtà, probabilmente dovrei chiarire il mio punto precedente: il principale limitatore di prestazioni sia per questa soluzione che per quella di don sarà direttamente correlato all'intervallo. Questa soluzione rallenterà con intervalli di dimensioni maggiori , mentre quella di don rallenterà con frequenze di intervallo maggiori . In altre parole, anche se il file di input è molto grande, se il verificarsi dell'intervallo effettivo è ancora molto raro, la sua soluzione è probabilmente la strada da percorrere. Tuttavia, se la dimensione dell'intervallo è relativamente gestibile ed è probabile che si verifichi spesso, questa è la soluzione che dovresti scegliere.
Quindi ecco il flusso di lavoro:
- Se
$matchsi trova nello spazio del modello preceduto da una \newline, elimina sedricorsivamente Dogni \newline che la precede.
$matchPrima stavo eliminando completamente lo spazio del modello, ma per gestire facilmente la sovrapposizione, lasciare un punto di riferimento sembra funzionare molto meglio.
- Ho anche cercato
s/.*\n.*\($match\)/\1/di provare a farlo in una volta sola e schivare il loop, ma quando $A/$Bsono grandi, il Dloop elete si rivela notevolmente più veloce.
- Quindi inseriamo la
Nriga ext di input preceduta da un \ndelimitatore di ewline e proviamo ancora una volta a Deliminare /\n.*$match/una ancora facendo riferimento alla nostra espressione regolare usata più di recente w / //.
- Se lo spazio del motivo corrisponde,
$matchallora può farlo solo con $matchall'inizio della linea - tutte le $Blinee precedenti sono state cancellate.
- Quindi iniziamo a fare un giro su
$After.
- Ogni esecuzione di questo ciclo cercheremo di
s///ubstitute per &sé $Al'esimo \ncarattere ewline nello spazio modello, e, in caso di successo, tEst saranno noi ramo - e tutta la nostra $Atampone opo - out dello script del tutto per avviare lo script sopra dall'alto con la successiva riga di input se presente.
- Se l'
test non è riuscita faremo branch di nuovo alla :tetichetta op e recurse per un'altra linea di input - possibilmente iniziare il ciclo su se $matchsi verifica durante la raccolta $Aopo.
- Se otteniamo oltre un
$matchciclo funzione, quindi cercheremo di pRint l' $ultima riga, se questo è vero, e se !non provate a s///ubstitute per &sé $Bl'esimo \ncarattere ewline nello spazio modello.
- Ci
tEst questo, troppo, e se è successo ci ramo per l' :Petichetta di Rint.
- Altrimenti torneremo all'operazione
:te aggiungeremo un'altra riga di input al buffer.
- Se ce la facciamo a
:Print, ci Printaccheremo, quindi Delimineremo fino alla prima \newline nello spazio modello e eseguiremo nuovamente lo script dall'alto con ciò che rimane.
E così questa volta, se lo stessimo facendo A=2 B=2 match=5; seq 5 | sed...
Lo spazio del modello per la prima iterazione a :Print sarebbe simile a:
^1\n2\n3$
Ed è così che sedraccoglie il suo precedente $Bbuffer. E così sedstampa sull'output $Bdelle linee di conteggio dietro l'input che ha raccolto. Questo significa che, dato il nostro esempio precedente, sedsarebbero PRint 1di uscita, e poi Delete che e rispedire alla parte superiore dello script di uno spazio modello che assomiglia a:
^2\n3$
... e nella parte superiore dello script Nviene recuperata la riga di input ext e quindi la prossima iterazione appare come:
^2\n3\n4$
E così quando troviamo la prima occorrenza di 5in input, lo spazio del pattern in realtà appare come:
^3\n4\n5$
Quindi Dentra in gioco il ciclo elete e quando è finito sembra:
^5$
E quando Nviene estratta la linea di input ext, sedcolpisce EOF e si chiude. A quel punto ha sempre e solo Psfilato le righe 1 e 2.
Ecco un esempio:
A=8 B=7 match='[24689]0'
seq 100 |
sed -ne:t -e"/\n.*$match/D" \
-e'$!N;//D;/'"$match/{" \
-e"s/\n/&/$A;t" \
-e'$q;bt' -e\} \
-e's/\n/&/'"$B;tP" \
-e'$!bt' -e:P -e'P;D'
Che stampa:
1
2
3
4
5
6
7
8
9
10
11
12
29
30
31
32
49
50
51
52
69
70
71
72
99
100