Si las líneas comentadas existentes forman un solo bloque contiguo, entonces podría coincidir desde la primera línea comentada, comentando solo aquellas líneas hasta e incluyendo su patrón final que aún no están comentados
sed '/^#/,/dotan/ s/^[^#]/#&/' file
Si los comentarios existentes no son contiguos, entonces, debido a la naturaleza codiciosa de la coincidencia de rango sed, creo que debería hacer algo como
tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac
es decir, hacer coincidir hacia arriba desde el patrón final hasta el "primer" comentario; obviamente, eso no es tan conveniente si quieres una solución in situ.
Puede manejar ambos casos (líneas comentadas en un solo bloque contiguo o intercaladas entre líneas no comentadas) con una sola sedinvocación:
sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile
Esto procesa solo las líneas en el 1,/PATTERN/rango. Se ae xcambios conservan el espacio w. espacio de patrón cada vez que se comenta una línea (por lo que nunca hay más de una línea comentada en el búfer de retención) y agrega cada línea que no está comentada al Hespacio anterior (cuando está en la primera línea, 1dy respectivamente 1h, también son necesarias para eliminar la inicial línea vacía en el búfer de retención).
Cuando alcanza el PATTERN que coincide con la línea, también lo agrega al Hbúfer anterior, e xcambia los búferes y luego reemplaza cada \ncarácter de línea ewline en el espacio del patrón con una \newline y a #(es decir, todas las líneas en el espacio del patrón ahora comenzarán con #, incluir la primera línea como la primera línea en el espacio de espera siempre es una línea comentada).
Con una muestra infile:
alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry
corriendo:
sed '1,/dotan/{ # if line is in this range -start c1
/^#/{ # if line is commented -start c2
x # exchage hold space w. pattern space
1d # if 1st line, delete pattern space
b # branch to end of script
} # -end c2
//!{ # if line is not commented -start c3
H # append to hold space
/dotan/!{ # if line doesn't match dotan -start c4
1h # if 1st line, overwrite hold space
d # delete pattern space
} # -end c4
//{ # if line matches dotan -start c5
x # exchage hold space w. pattern space
s/\n/&#/g # add # after each newline character
} # -end c5
} # -end c3
}' infile # -end c1
salidas:
alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry
así que solo comenta líneas desde (y excluye) #charliehasta (e incluye) dotany deja las otras líneas intactas.
Claro, esto supone que siempre hay al menos una línea comentada antes de la coincidencia de línea PATTERN. Si ese no es el caso, puede agregar un cheque adicional antes del reemplazo:/^#/{s/\n/&#/g}
¡Gracias, tendré mucho que aprender de esta respuesta!
dotancohen
Espera, debo haber jodido. ¿No se trata de la última serie de líneas comentadas? No, lo entiendo, lo es. La última serie + dotan. Bastante inteligente.
mikeserv
1
Siempre encuentras las mejores preguntas. Maldito dotan me hizo tirar por un tiempo, tal vez todavía lo hace, aún no lo he probado. gracias don
Eso hace lo que pides. Simplemente funciona en una pila, construyéndolo cuando sea necesario y durante el tiempo que sea necesario entre las ocurrencias de las líneas comentadas, y volcando el búfer viejo a favor de la nueva línea comentada más adelante en la entrada cuando encuentra una. Imagen...
Lo siento, no sé por qué hice eso. Pero me vino a la mente.
De todos modos, sedextiende sus búferes entre cada última línea comentada en cualquier serie, sin retener nunca más en su búfer de lo necesario para rastrear con precisión la última ocurrencia comentada, y si en algún momento encuentra la última línea mientras lo hace, intentará la gdeclaración final de ejecución lobal y la ramificación testán imprimiendo todo el búfer, de lo contrario borrará Ptodas las líneas que libera de su búfer tan pronto como lo haga.
Supongo que esto es lo que me hizo pensar en los acordeones ...
printf %s\\n \#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric |
sed -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D
#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric
Solo hay una diferencia entre este comando y el anterior y ese es el lcomando ook en la parte superior. Cuando lOOK en sed's espacio de patrones, ya que funciona podemos tener una mejor idea de lo que sucede detrás de las escenas y una mejor comprensión de cómo dirigir sus esfuerzos.
En este caso, podemos observar la sedentrada de la pila hasta que haya encontrado una segunda aparición de \n#.*\ndotanentrada, y eso cuando comience a imprimir la línea anterior de una en una. Es un poco genial. Aprendí mucho trabajando en esto.
¡Muy bonito, gracias! El párrafo final con explicaciones es excelente, también pasaré bastante tiempo aprendiendo de esta publicación. Buena pila!
dotancohen
1
@dotancohen: esta fue una muy buena pregunta. Echa un vistazo a la edición para ver la pila .
mikeserv
2
Noto en la historia de edición la entrada Handle many dotans. Estoy seguro de que esta es la peor pesadilla de mi esposa.
dotancohen
1
@dotancohen: sí, fue difícil. Cosas como #\ndotan\ndotanes difícil para estas cosas. Lo digo en serio cuando digo esto, una buena pregunta. Yo creo que lo tengo casi perfecto, pero un problema que podría ejecutar en es si sus bloques de comentarios están separados por 1000 líneas - que va a reducir la velocidad. Puede pegar algo como s/\n/&/150;tantes de lo primero /\n#para romper el búfer si abarca 150 líneas, por ejemplo. Y de todos modos, ¡tal vez es justo lo que ha estado esperando todo el tiempo !
Aquí hay otro
sed
:Eso hace lo que pides. Simplemente funciona en una pila, construyéndolo cuando sea necesario y durante el tiempo que sea necesario entre las ocurrencias de las líneas comentadas, y volcando el búfer viejo a favor de la nueva línea comentada más adelante en la entrada cuando encuentra una. Imagen...
Lo siento, no sé por qué hice eso. Pero me vino a la mente.
De todos modos,
sed
extiende sus búferes entre cada última línea comentada en cualquier serie, sin retener nunca más en su búfer de lo necesario para rastrear con precisión la última ocurrencia comentada, y si en algún momento encuentra la última línea mientras lo hace, intentará lag
declaración final de ejecución lobal y la ramificaciónt
están imprimiendo todo el búfer, de lo contrario borraráP
todas las líneas que libera de su búfer tan pronto como lo haga.Supongo que esto es lo que me hizo pensar en los acordeones ...
Solo hay una diferencia entre este comando y el anterior y ese es el
l
comando ook en la parte superior. Cuandol
OOK ensed
's espacio de patrones, ya que funciona podemos tener una mejor idea de lo que sucede detrás de las escenas y una mejor comprensión de cómo dirigir sus esfuerzos.En este caso, podemos observar la
sed
entrada de la pila hasta que haya encontrado una segunda aparición de\n#.*\ndotan
entrada, y eso cuando comience a imprimir la línea anterior de una en una. Es un poco genial. Aprendí mucho trabajando en esto.fuente
Handle many dotans
. Estoy seguro de que esta es la peor pesadilla de mi esposa.#\ndotan\ndotan
es difícil para estas cosas. Lo digo en serio cuando digo esto, una buena pregunta. Yo creo que lo tengo casi perfecto, pero un problema que podría ejecutar en es si sus bloques de comentarios están separados por 1000 líneas - que va a reducir la velocidad. Puede pegar algo comos/\n/&/150;t
antes de lo primero/\n#
para romper el búfer si abarca 150 líneas, por ejemplo. Y de todos modos, ¡tal vez es justo lo que ha estado esperando todo el tiempo !