don puede ser mejor en la mayoría de los casos, pero en caso de que el archivo sea realmente grande y no pueda sedmanejar 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 $Blí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
$matchse encuentra en un espacio de patrón precedido por una línea de \nflujo, sedelegirá recursivamente Dcada línea de \nflujo que lo precede.
- Antes estaba limpiando
$matchcompletamente 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/$Bson grandes, el Dbucle elete prueba considerablemente más rápido.
- Luego, extraemos la
Nlínea de entrada de extensión precedida por un \ndelimitador de línea de línea e intentamos nuevamente Delegir una de /\n.*$match/nuevo refiriéndonos a nuestra expresión regular w / utilizada más recientemente //.
- Si el espacio de patrón coincide,
$matchentonces solo puede hacerlo $matchal principio de la línea: todas las $Blíneas anteriores se han borrado.
- Entonces comenzamos a dar vueltas
$Adespués.
- Cada ejecución de este bucle vamos a tratar de
s///ubstitute por &sí misma el $AXX \ncarácter ewline en el espacio de patrones, y, si tiene éxito, test nos BRANCH - y toda nuestra $Amemoria 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
test no tiene éxito, bvolveremos a la :tetiqueta de operación y recurriremos a otra línea de entrada, posiblemente comenzando el ciclo nuevamente si $matchocurre mientras se recolecta $Adespués.
- Si conseguimos más allá de un
$matchbucle de función, entonces vamos a tratar de print la $última línea, si esto es así, y si !no tratar de s///ubstitute por &sí misma el $BXX \ncarácter ewline en el espacio patrón.
- También consideraremos
testo, y si tiene éxito, pasaremos a la :Petiqueta de la pista.
- Si no, volveremos a
:toperar y obtendremos otra línea de entrada añadida al búfer.
- Si llegamos a
:Print, vamos a rint, Pluego Delegiremos hasta la primera línea de \newline 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 :Print se vería así:
^1\n2\n3$
Y así es como sedreúne su $Bbuffer antes. Y así se sedimprime en las $Blíneas de conteo de salida detrás de la entrada que ha reunido. Esto significa que, dado nuestro ejemplo anterior, se seddaría una Ppista 1al resultado, y luego lo Delegirí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 Nse 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 5entrada, el espacio del patrón en realidad se ve así:
^3\n4\n5$
Luego, el Dbucle elete se activa y cuando termina, se ve así:
^5$
Y cuando Nse tira de la línea de entrada ext sedgolpea EOF y se cierra. En ese momento, solo ha Pborrado 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