En esta edición,
Stéphane Chazelas POSIXifica (nuevamente) mi sed
formato insertando un -e
salto de expresión y otra -e
declaración de expresión. Ahora, podría preguntarle por qué en los comentarios, supongo, pero ya es la revisión número 18 en esa respuesta y casi todas las anteriores ya fueron gracias a regalos similares (si puede ver comentarios eliminados, sabrá qué me refiero) . Además, creo que estoy lo suficientemente cerca como para entender por qué expresar esto de una manera que podría ser más útil en general. Así que aquí está esperando ...
En general, prefiero mantener mi sed
-e
xpressions total en uno si pudiera, pero también tengo una mayor preferencia por cumplir con la especificación lo más cerca posible, especialmente cuando la diferencia no es más que ay <space>
an -e
. Pero no puedo hacer esto si no entiendo por qué debería hacerlo. Aquí hay un breve resumen del estado actual de mi comprensión:
la
' -e '
ruptura puede representar portátilmente unased
secuencia de comandos\n
ewline break en unased
declaración de línea de comando ... Estoy ciertamente confuso sobre por quéla llave de cierre en una
sed
{
función}
debe estar precedida por un\n
salto de línea de conexión como se indica aquí:- El
<right-brace>
debe ir precedido de a<newline>
y puede ir precedido o seguido de<blank>
caracteres.
- El
una
\n
ruptura ewline se requiere de manera similar después de cualquier uso de ...a
,b
,c
,i
,r
,t
,w
, o:
.
Pero no entiendo claramente cómo la definición de la {
función }
se relaciona con el !
operador no. La única mención que encuentro del operador de negación en los estados de especificación:
- 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.
¿Significa esto que el uso de a !
implica {
llaves }
? ¿Qué pasa con los $!
comandos? ¿Deberían también estar separados por ' -e '
saltos? ¿Fue esto lo que se abordó cuando Stéphane más recientemente POSIXificó mi respuesta?
Creo que es el !
operador de negación o la b
declaración de rancho que aborda en su edición, o posiblemente ambas cosas a la vez, pero no lo sé y me gustaría. Si es solamente la b
declaración de hacienda, entonces creo un d
haría en su lugar y eliminar la necesidad de la ' -e '
ruptura, pero yo prefiero estar seguro antes de arriesgar un tres veces POSIXified respuesta. ¿Puede usted ayudar?
Lo arriesgué después de todo , pero no con mucha certeza ...
b;n;:b
, se está bifurcando a la etiqueta llamada";n;:b"
en seds históricos y POSIX (y GNU sed no está en ese sentido).:
papel - condujiste a casa hace meses. Pero no entiendo completamente por qué el segundosed
comando se POSIXificó de manera similar .sed
está muy clara para mí. He solicitado aclaraciones varias veces en el pasado, pero no creo que se haya actualizado como resultado. Una buena prueba es probar con el hecheloom toolchest (uno de Solaris, derivado del original y en el que se basa en gran medida la especificación POSIX).s///
sustituciones están especificadas para aceptar el encadenamiento con a ; . se vuelve borroso alrededor de los comandos que deben delimitarse con una nueva línea y cómo-e
puede intervenir en ese caso, al menos para mí. Sin embargo, todavía tengo que tropezar con unsed
que no los interpreta de manera bastante intercambiable.;
antes de una nueva línea, una nueva línea está bien. Honestamente, podría prescindir del-e
y todo por completo y simplemente escribir un archivo como#!/bin/sed
con cada comando en una nueva línea, o aquellos que no requieren tales delimitadores en su lugar delimitados;
. Los que lo requieren nuevas líneas son generalmente los que tienen de entrada arbitrarias -:
nombres de las etiquetas y los comandos que se refieren a ellos comob
ot
o cerrar}
curlies para las funciones, or
EAD yw
rito que toman argumentos de nombre de archivo. Todos ellos deben ser seguidos de forma portátil\n
.Respuestas:
Así que ya es hora de que esta pregunta tenga una respuesta, y, aunque eventualmente resolví intuitivamente cómo hacerlo correctamente en casi todos los casos hace algún tiempo, solo recientemente logré concretar bastante esa comprensión con el texto en el estándar . En realidad, se afirma allí de manera bastante simple: supongo que lo pasé por alto estúpidamente muchas veces.
Las partes relevantes del texto se encuentran todas bajo el encabezado ...
Edición de comandos en
sed
:El texto del argumento consistirá en una o más líneas. Cada línea
\n
electrónica incrustada en el texto irá precedida de una\
barra diagonal inversa. Se eliminarán otras barras invertidas en el texto y el siguiente carácter se tratará literalmente.Los verbos de comando
r
yw
, y elw
indicador als
comando, toman un parámetro opcional rfile (o wfile ), separado de la letra o indicador del verbo de comando por uno o más<blank>s
; Las implementaciones pueden permitir la separación cero como una extensión.Comando verbos que no sea
{
,a
,b
,c
,i
,r
,t
,w
,:
, y#
puede ser seguido por un;
punto y coma, opcional<blank>s
, y otro verbo de comando. Sin embargo, cuando els
verbo de comando se usa con law
bandera, seguirlo con otro comando de esta manera produce resultados indefinidos....en...
Opciones: se pueden especificar múltiples
-e
y-f
opciones. Todos los comandos se agregarán al script en el orden especificado, independientemente de su origen.-e
script : agregue los comandos de edición especificados por el argumento de opción de script al final del script de comandos de edición. El argumento de opción de script tendrá las mismas propiedades que el operando del script , descrito en la sección OPERANDS .-f
script_file : agrega los comandos de edición en el archivo script_file al final del script.Y último en ...
Operandos:
\n
electrónica.Entonces, cuando lo toma en conjunto, tiene sentido que cualquier comando que esté opcionalmente seguido de un parámetro arbitrario sin un delimitador predefinido (en oposición a,
s d sub d repl d flag
por ejemplo) se delimite en una línea de escape sin escape\n
.Es discutible que
;
sea un delimitador predefinido, pero en ese caso el uso;
de cualquiera de los[aic]
comandos requeriría que se incluyera un analizador por separado en la implementación específicamente para esos tres comandos[:brw]
, por ejemplo , separado del analizador utilizado . O de lo contrario, la implementación tendría que requerir que;
también se escape la barra invertida dentro del parámetro de texto y solo se vuelva más complicado a partir de ahí.Si yo estuviera escribiendo una
sed
que anhelaba ser a la vez compatible y eficiente, entonces yo no escribiría un programa de análisis tales separada, espero que - a excepción de que tal vez[aic]
deberían generación de un error de sintaxis si no es seguido inmediatamente por un\n
ewline. Pero ese es un problema de tokenización simple: el caso del delimitador final es generalmente el más problemático. Simplemente lo escribiría así:...y...
... se comportaría de manera muy similar, ya que el primero crearía y escribiría en un archivo llamado:
... y el segundo agregaría un bloque de texto a la línea actual en la salida como ...
... porque ambos compartirían el mismo código de análisis para el parámetro.
Y con respecto al tema
{ ... }
y$!
, bueno, estaba lejos. Un solo comando precedido por una dirección no es una función, sino que es solo un comando direccionado. Casi todos los comandos, incluida la{
definición de funciones,}
se especifican para aceptar/one/
o/one/,/two/
direcciones, con la excepción de la definición de#
comentarios y:
etiquetas . Y una dirección puede ser un número de línea o un expreso regular y se puede negar con!
. Entonces todos ...... puede ir seguido de uno
;
y más comandos de acuerdo con el estándar, pero si se requieren más comandos para una sola dirección, y esa dirección no debe reevaluarse después de la ejecución de cada comando, entonces se debe usar una{
función}
como:... donde
{
no se puede seguir en la misma línea un cierre}
y ese cierre}
no puede ocurrir excepto al comienzo de una línea. Pero si un comando contenido no debería ser seguido por una línea\n
electrónica, entonces tampoco necesita dentro de la función. Por lo tanto, todas lass///
sustituciones anteriores , e incluso la}
llave de cierre , pueden seguirse de forma portátil con;
punto y coma y otros comandos.Sigo hablando de
\n
delimitadores ewline, pero la pregunta es sobre-e
las declaraciones de xpression, lo sé. Pero los dos son realmente uno y lo mismo, y la relación clave es que un script puede ser un argumento de línea de comandos literal o un archivo con cualquiera de los dos-[ef]
, y que ambos se interpretan como archivos de texto (que se especifican para terminar en un\n
ewline) pero ninguna de las dos tiene que terminar en\n
ewline. Con esto puedo deducir razonablemente (espero) que un\0NUL
argumento delimitado implica una línea de\n
ew final , y como todos los argumentos de invocación obtienen al menos) un\0NUL
delimitador de todos modos, entonces cualquiera debería funcionar bien.De hecho, en la práctica, en todos los casos, excepto uno en el que el estándar especifica
\
que se requiere una barra invertida con escape de nueva línea, he encontrado ...... para trabajar igual de bien. Y en todos los casos, una vez más, en la práctica, en los
\n
que se debe requerir una línea electrónica sin escape ...... también ha funcionado para mí. La única excepción que menciono arriba es ...
... que no funciona para ninguna implementación en ninguna de mis pruebas. Estoy bastante seguro de que eso se remonta al requisito del archivo de texto y al hecho de que
s///
viene con un delimitador y, por lo tanto, no hay ninguna razón para que una sola declaración abarque\0NUL
argumentos delimitados.Entonces, en conclusión, aquí hay un breve resumen de formas portátiles de escribir varios tipos de
sed
comandos:Para cualquiera de
[aic]
:...o...
Para cualquiera de
[:rwtb]
donde el parámetro es opcional (para todos menos:
), pero la línea de delimitación no lo\n
es . Tenga en cuenta que nunca he tenido una razón para tratar de varias líneas de etiqueta parámetros que se utilizaría con , pero que riting / LECTURA a varias líneas en [RW] archivo de parámetros se acepta generalmente sin lugar a dudas por s He probado tanto tiempo como el incrustado ewline se escapa con una barra invertida. Aún así, el estándar no especifica directamente que la etiqueta y los parámetros del archivo [rw] deben analizarse de manera idéntica al texto[:tb]
w
r
sed
\n
\
parámetros y no hace mención de\n
ewlines con respecto a los dos primeros, excepto porque los delimita....o...
... donde lo
<space>
anterior es opcional para[:tb]
.Y última...
...o...
... donde cualquiera de los comandos antes mencionados (excepto
:
) también acepta al menos una dirección y que puede ser una/
expresión regular/
o un número de línea y podría negarse!
, pero si se necesita más de un comando para una sola evaluación de la dirección, entonces{
Se}
deben utilizar llaves de delimitación de contexto de función . Una función puede contener incluso múltiples\n
comandos delimitados por ewline, pero cada uno debe estar delimitado dentro de las llaves como lo sería de otra manera.Y así es como escribir
sed
scripts portátiles .fuente