La documentación de POSIX sed decía:
Una función puede estar precedida por uno o más '!' caracteres, en cuyo caso la función se aplicará si las direcciones no seleccionan el espacio del patrón. Se aceptarán cero o más caracteres <en blanco> antes del primer '!' personaje. No se especifica si los caracteres <en blanco> pueden seguir a '!' carácter, y las aplicaciones conformes no seguirán un '!' carácter con caracteres <en blanco>.
Entonces, con cualquier POSIX sed, podemos:
sed -e '/pattern/!d' file
Es lo mismo que escribir:
sed -e '/pattern/!!d' file
Y !!!d
y n
de los signos de exclamación todavía están bien (Probado con tres sed
versiones de heirloom toolchest ). No veo ningún beneficio entre múltiples en lugar de una exclamación.
¿Por qué la especificación permitió esa sintaxis y cómo es útil en la aplicación del mundo real?
Parece que GNU sed no es compatible en este caso, se quejará si usamos múltiples exclamaciones:
$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s
!
actúa como un conmutador,/pattern/!!
es lo mismo/pattern/
y/pattern/!!!
es lo mismo que/pattern/!
. En FreeBSD, múltiples!
son lo mismo que uno solo.sed
se pueden generar scripts . Dado un POSIXsed
, debería ser realmente sencillo escribir la escritura de unased
secuencia de comandos. Entonces, si tuvo algún desencadenante para algún caso que debería marcar una dirección!
no digna de lo que fue su acción, incluso podría desencadenar eso varias veces para el mismo y aún así obtener los mismos resultados.sed
no lo son.Respuestas:
sed
La API es primitiva, y esto es por diseño. Al menos, se ha mantenido primitivo por diseño, no puedo decir si fue diseñado primitivamente desde el principio. En la mayoría de los casos, la escritura de unsed
script que, cuando se ejecuta, generará otrosed
script es una cuestión simple.sed
Muy a menudo se aplica de esta manera por preprocesadores macro comom4
y / omake
.(Lo que sigue es un caso de uso altamente hipotético: es un problema diseñado para adaptarse a una solución. Si se siente como una exageración para usted, entonces probablemente sea porque sí, pero eso no necesariamente lo hace menos válido).
Considere el siguiente archivo de entrada:
Si quisiéramos escribir una
sed
secuencia de comandos que anexaría el caso de palabras al final de cada palabra apropiada en el archivo de entrada anterior solo si pudiera encontrarse en una línea en el contexto apropiado , y deseamos hacerlo de la manera más eficiente posible ( como debería ser nuestro objetivo, por ejemplo, durante una operación de compilación), entonces deberíamos preferir evitar aplicar/
expresiones regulares/
tanto como sea posible.Una cosa que podríamos hacer es editar previamente el archivo en nuestro sistema en este momento, y nunca llamar
sed
en absoluto durante la compilación. Pero si alguna de esas palabras en el archivo se incluye o no en función de la configuración local y / o las opciones de tiempo de compilación, es probable que hacerlo no sea una alternativa deseable.Otra cosa que podríamos hacer es procesar el archivo ahora contra expresiones regulares. Podemos producir, e incluir en nuestra compilación, un
sed
script que puede aplicar ediciones según el número de línea, que suele ser una ruta mucho más eficiente a largo plazo.Por ejemplo:
... que escribe la salida en forma de
sed
script y que se parece a ...Cuando esa salida se guarda en un archivo de texto ejecutable en mi máquina con el nombre
./bang.sed
y se ejecuta como./bang.sed ./infile
, la salida es:Ahora podrías preguntarme ... ¿Por qué querría hacer eso? ¿Por qué no simplemente anclar
grep
los partidos? ¿Quién usa camel-case de todos modos? Y a cada pregunta que solo podía responder, no tengo idea ... porque no. ¡Antes de leer esta pregunta, nunca había notado personalmente el multi-! requisito de análisis en la especificación: creo que es una buena captura.El multi-! Sin embargo, esto inmediatamente tenía sentido para mí: gran parte de la
sed
especificación está orientada a scripts simplemente analizados y simplemente generadossed
. Probablemente encontrará los\n
delimitadores de línea electrónica necesarios para[wr:bt{]
tener mucho más sentido en ese contexto, y si tiene en cuenta esa idea, podría tener un mejor sentido de algunos otros aspectos de la especificación (como:
no aceptar direcciones yq
negarse a aceptar más de 1) .En el ejemplo anterior, escribo una cierta forma de
sed
script que solo se puede leer una vez. Si lo mira detenidamente, puede notar que a medida quesed
lee el archivo de edición, progresa de un bloque de comandos al siguiente: nunca se bifurca o completa su script de edición hasta que haya terminado completamente con su archivo de edición.Considero que multi-! las direcciones pueden ser más útiles en ese contexto que en algunos otros, pero, sinceramente, no puedo pensar en un solo caso en el que podría haberle dado un uso muy bueno, y yo
sed
mucho. También creo que es digno de mención quesed
ambos GNU / BSD no logran manejarlo como se especifica: probablemente este no sea un aspecto de la especificación que tenga mucha demanda, por lo que si una implementación lo pasa por alto, dudo mucho que sus errores @ box sufran terriblemente como resultado.Dicho esto, no manejar esto como se especifica es un error para cualquier implementación que pretenda cumplir, por lo que creo que enviar un correo electrónico a los cuadros de desarrollo relevantes se requiere aquí, y tengo la intención de hacerlo si no lo hace.
fuente
!
se eliminará en la próxima especificación , ¡qué está pasando aquí!