É portátil recuar o argumento do comando 'i\' do sed?

É portátil recuar o argumento do comando 'i\' do sed?

Fiquei com a impressão doEspecificações POSIX parasedque é necessário alinhar o texto à esquerda na linha após o i\comando, a menos que você queira espaços em branco à esquerda na saída.

Um teste rápido no meu Mac (usando BSD sed) mostra que talvez seja issonãonecessário:

$ 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
$ 

No entanto, não consigo encontrar isso documentado em lugar nenhum. Não está nas especificações POSIX e nem está na sedpágina de manual do meu sistema.

Posso confiar nesse comportamento em sedscripts que desejo que sejam portáveis? Quão portátil é?

(Está documentadoem qualquer lugar?)


(Pergunta bônus: é possível forçar seda inserção de espaços em branco no início de uma linha fixa passada para i\?)

Responder1

Não, mas seu script será portátil, desde que você escape de qualquer espaço em branco inicial. Por que ? Porque alguns seds retiram os caracteres em branco das linhas de texto e a única maneira de evitar isso é escapar do espaço em branco inicial, como explicam estas páginas de manual que datam do século passado:1,2,3
O mesmo vale para BSD sed( OSXapenas copiei o código, não é a extensão deles) e se você verificar os arquivos e ler omanpágina deBSD 2.11está bem claro:

(1)eu\
texto
.......
Um argumento denotadotextoconsiste em uma ou mais linhas, todas, exceto a última, terminam com '\'para ocultar a nova linha. As barras invertidas no texto são tratadas como barras invertidas na string de substituição de um 's' comando e podem ser usadas para proteger espaços em branco e tabulações iniciais contra a remoção feita em cada linha do script.

Agora, onde isso está documentado nas especificações POSIX? Só diz

O texto do argumento deve consistir em uma ou mais linhas. Cada <nova linha> incorporada no texto deve ser precedida por uma <barra invertida>. Outros caracteres <barra invertida> no texto devem ser removidos e o caractere seguinte deve ser tratado literalmente.

e se você rolar para baixoJUSTIFICATIVAdiz

Os requisitos para aceitação de caracteres <espaço> e <espaço> nas linhas de comando foram tornados mais explícitos do que nas propostas anteriores para descrever claramente a prática histórica e para remover a confusão sobre a frase "proteger espaços em branco iniciais [sic] e tabulações da remoção isso é feito em cada linha do script" que aparece em grande parte da documentação histórica da descrição de texto do utilitário sed. (Nem todas as implementações são conhecidas por terem removido caracteres <em branco> das linhas de texto, embora todas tenham permitido caracteres <em branco> iniciais precedendo o endereço em uma linha de comando.)

Já a parte com"barras invertidas podem ser usadas para"não foi incluída nessa citação, a frase restante"proteger os espaços em branco iniciais..."não faz sentido... 1


De qualquer forma, para resumir: algumas implementações removeram (e algumas ainda removem) os espaços em branco das linhas de texto. No entanto, uma vez que a especificação POSIX à qual todas as implementações devem obedecer diz

Outros caracteres <barra invertida> no texto devem ser removidos e o caractere seguinte deve ser tratado literalmente.

podemos concluir que a maneira portátil de recuar as linhas no texto a ser inserido é escapando do espaço em branco inicial em cada uma dessas linhas.


1: Também não entendo por que OSXas BSDpessoas alteraram o parágrafo inteiro da manpágina sem alterar o código-fonte - você obtém o mesmo comportamento de antes, mas a seção man que documenta essas coisas não está mais lá.

Responder2

É seduma extensão OSX, não um comportamento padrão. Você pode vereste link, em funçãocompile_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 

Eles comeram espaços usando EATSPACEmacro.

No FreeBSD sed, que pode tratar incorretamente \como caracteres de continuação de linha ao usar a, i, c, o comportamento é mais estranho. No meu FreeBSD 9.3:

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

mas:

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

funciona e também consome espaços.

GNU sed, a herança sednão tem esse problema.

Responder3

Cuonglmdeu a melhor resposta, mas para que conste aqui está o queGNU sedfaz:

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

Saída:

     This line starts with spaces.
foo

informação relacionada