don puede ser mejor en la mayoría de los casos, pero en caso de que el archivo sea realmente grande y no pueda sed
manejar un archivo de script tan grande (que puede suceder en más de 5000 líneas de script) , aquí está con simple 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'
Este es un ejemplo de lo que se llama una ventana deslizante en la entrada. Funciona mediante la construcción de un preanálisis de amortiguamiento de las $B
líneas -Contar incluso antes de intentar imprimir nada.
Y en realidad, probablemente debería aclarar mi punto anterior: el limitador de rendimiento primario tanto para esta solución como para el don estará directamente relacionado con el intervalo. Esta solución se ralentizará con intervalos de mayor tamaño , mientras que la de don disminuirá con frecuencias de intervalo más grandes . En otras palabras, incluso si el archivo de entrada es muy grande, si la ocurrencia del intervalo real es muy poco frecuente, entonces su solución es probablemente el camino a seguir. Sin embargo, si el tamaño del intervalo es relativamente manejable y es probable que ocurra con frecuencia, entonces esta es la solución que debe elegir.
Así que aquí está el flujo de trabajo:
- Si
$match
se encuentra en un espacio de patrón precedido por una línea de \n
flujo, sed
elegirá recursivamente D
cada línea de \n
flujo que lo precede.
- Antes estaba limpiando
$match
completamente el espacio del patrón, pero para manejar fácilmente la superposición, dejar un hito parece funcionar mucho mejor.
- También traté
s/.*\n.*\($match\)/\1/
de intentarlo de una vez y esquivar el bucle, pero cuando $A/$B
son grandes, el D
bucle elete prueba considerablemente más rápido.
- Luego, extraemos la
N
línea de entrada de extensión precedida por un \n
delimitador de línea de línea e intentamos nuevamente D
elegir una de /\n.*$match/
nuevo refiriéndonos a nuestra expresión regular w / utilizada más recientemente //
.
- Si el espacio de patrón coincide,
$match
entonces solo puede hacerlo $match
al principio de la línea: todas las $B
líneas anteriores se han borrado.
- Entonces comenzamos a dar vueltas
$A
después.
- Cada ejecución de este bucle vamos a tratar de
s///
ubstitute por &
sí misma el $A
XX \n
carácter ewline en el espacio de patrones, y, si tiene éxito, t
est nos BRANCH - y toda nuestra $A
memoria intermedia espués - fuera del guión completo para iniciar el script más de la parte superior con la siguiente línea de entrada si la hay.
- Si el
t
est no tiene éxito, b
volveremos a la :t
etiqueta de operación y recurriremos a otra línea de entrada, posiblemente comenzando el ciclo nuevamente si $match
ocurre mientras se recolecta $A
después.
- Si conseguimos más allá de un
$match
bucle de función, entonces vamos a tratar de p
rint la $
última línea, si esto es así, y si !
no tratar de s///
ubstitute por &
sí misma el $B
XX \n
carácter ewline en el espacio patrón.
- También consideraremos
t
esto, y si tiene éxito, pasaremos a la :P
etiqueta de la pista.
- Si no, volveremos a
:t
operar y obtendremos otra línea de entrada añadida al búfer.
- Si llegamos a
:P
rint, vamos a rint, P
luego D
elegiremos hasta la primera línea de \n
ewline en el espacio del patrón y volveremos a ejecutar el script desde arriba con lo que queda.
Y esta vez, si estuviéramos haciendo A=2 B=2 match=5; seq 5 | sed...
El espacio del patrón para la primera iteración en :P
rint se vería así:
^1\n2\n3$
Y así es como sed
reúne su $B
buffer antes. Y así se sed
imprime en las $B
líneas de conteo de salida detrás de la entrada que ha reunido. Esto significa que, dado nuestro ejemplo anterior, se sed
daría una P
pista 1
al resultado, y luego lo D
elegiría y enviaría de nuevo a la parte superior del script un espacio de patrón que se parece a:
^2\n3$
... y en la parte superior de la secuencia de comandos N
se recupera la línea de entrada ext y, por lo tanto, la siguiente iteración se ve así:
^2\n3\n4$
Y así, cuando encontramos la primera aparición de 5
entrada, el espacio del patrón en realidad se ve así:
^3\n4\n5$
Luego, el D
bucle elete se activa y cuando termina, se ve así:
^5$
Y cuando N
se tira de la línea de entrada ext sed
golpea EOF y se cierra. En ese momento, solo ha P
borrado las líneas 1 y 2.
Aquí hay un ejemplo de ejecución:
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'
Que imprime:
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