¿Es portátil sangrar el argumento del comando 'i\' de sed?

¿Es portátil sangrar el argumento del comando 'i\' de sed?

Tenía la impresión de queEspecificaciones POSIX parasedque es necesario alinear a la izquierda el texto en la línea que sigue al i\comando, a menos que desee espacios en blanco al principio en la salida.

Una prueba rápida en mi Mac (usando BSD sed) muestra que tal vez esto seanonecesario:

$ cat test.sed 
#!/bin/sed -f
i\
      This line starts with spaces.
$ echo some text | sed -f test.sed
This line starts with spaces.
some text
$ 

Sin embargo, parece que no puedo encontrar esto documentado en ninguna parte. No está en las especificaciones POSIX y ni siquiera está en sedla página de manual de mi sistema.

¿Puedo confiar en este comportamiento en sedscripts que quiero que sean portátiles? ¿Qué tan portátil es?

(¿Está documentado?¿en cualquier lugar?)


(Pregunta adicional: ¿Es posible forzar sedla inserción de espacios en blanco al comienzo de una línea fija pasada a i\?)

Respuesta1

No, pero su secuencia de comandos será portátil siempre que escape de cualquier espacio en blanco inicial. Por qué ? Porque algunos sedanuncios eliminan los caracteres en blanco de las líneas de texto y la única forma de evitarlo es escapar del espacio en blanco inicial, como explican estas páginas de manual que datan del siglo pasado:1,2,3
Lo mismo ocurre BSD sed( OSXsimplemente copié el código, no es su extensión) y si revisa los archivos y lee elmanpágina deBSD 2.11está bastante claro:

(1)yo\
texto
.......
Un argumento denotadotextoconsta de una o más líneas, todas menos la última terminan con '\'para ocultar la nueva línea. Las barras invertidas en el texto se tratan como barras invertidas en la cadena de reemplazo de un 's' comando y pueden usarse para proteger los espacios en blanco y tabulaciones iniciales contra la eliminación que se realiza en cada línea de script.

Ahora bien, ¿dónde está documentado esto en la especificación POSIX? solo dice

El texto del argumento constará de una o más líneas. Cada <nueva línea> incrustada en el texto deberá estar precedida por una <barra invertida>. Se eliminarán otros caracteres <barra invertida> del texto y el siguiente carácter se tratará literalmente.

y si te desplazas hacia abajoRAZÓN FUNDAMENTALdice

Los requisitos para la aceptación de caracteres <en blanco> y <espacio> en las líneas de comando se han hecho más explícitos que en las primeras propuestas para describir claramente la práctica histórica y eliminar la confusión sobre la frase "proteger los espacios en blanco iniciales [sic] y las pestañas de la eliminación". eso se hace en cada línea de script" que aparece en gran parte de la documentación histórica de la descripción del texto de la utilidad sed. (No todas las implementaciones han eliminado los caracteres <en blanco> de las líneas de texto, aunque todas han permitido caracteres <en blanco> iniciales que preceden a la dirección en una línea de comando).

Desde la parte con"Se pueden utilizar barras invertidas para"no estaba incluida en esa cita, la frase restante"proteger los espacios en blanco iniciales..."no tiene ningún sentido... 1


De todos modos, para resumir: algunas implementaciones eliminaron (y algunas todavía lo hacen) los espacios en blanco de las líneas de texto. Sin embargo, dado que la especificación POSIX que deben cumplir todas las implementaciones dice

Se eliminarán otros caracteres <barra invertida> del texto y el siguiente carácter se tratará literalmente.

Podemos concluir que la forma portátil de sangrar las líneas en el texto que se va a insertar es escapando del espacio en blanco inicial en cada una de esas líneas.


1: Tampoco entiendo por qué OSXla BSDgente ha cambiado todo el párrafo de la manpágina sin alterar el código fuente; obtienes el mismo comportamiento que antes, pero la sección man que documenta estas cosas ya no está ahí.

Respuesta2

Es seduna extensión de OSX, no un comportamiento estándar. Puedes vereste enlace, en funcióncompile_text:

/*
 * Compile the text following an a or i command.
 */
static char *
compile_text()
{
    int asize, size;
    char *text, *p, *op, *s;
    char lbuf[_POSIX2_LINE_MAX + 1];

    asize = 2 * _POSIX2_LINE_MAX + 1;
    text = xmalloc(asize);
    size = 0;
    while (cu_fgets(lbuf, sizeof(lbuf))) {
        op = s = text + size;
        p = lbuf;
        EATSPACE();
        for (; *p; p++) {
            if (*p == '\\')
                p++;
            *s++ = *p;
        }
        size 

Se comieron espacios usando EATSPACEmacro.

En FreeBSD sed, que puede tratar incorrectamente \caracteres de continuación de línea cuando se usa ,,, ael comportamiento es más extraño. En mi FreeBSD 9.3:ic

$ echo 1 | sed -e 'i\ 1'
": extra characters after \ at the end of i command

pero:

$ echo 1 | sed -e 'i\
 2'
2
1

Funciona y también come espacios.

GNU sed, la reliquia familiar, sedno tiene este problema.

Respuesta3

Cuonglmdio la mejor respuesta, pero para que conste esto es lo queÑU sedhace:

echo foo | sed 'i\
     This line starts with spaces.'

Producción:

     This line starts with spaces.
foo

información relacionada