Fiquei com a impressão doEspecificações POSIX parased
que é 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 sed
página de manual do meu sistema.
Posso confiar nesse comportamento em sed
scripts que desejo que sejam portáveis? Quão portátil é?
(Está documentadoem qualquer lugar?)
(Pergunta bônus: é possível forçar sed
a 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 sed
s 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
( OSX
apenas copiei o código, não é a extensão deles) e se você verificar os arquivos e ler oman
página deBSD 2.11
está 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 OSX
as BSD
pessoas alteraram o parágrafo inteiro da man
pá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
É sed
uma 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 EATSPACE
macro.
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 sed
não tem esse problema.
Responder3
Cuonglmdeu a melhor resposta, mas para que conste aqui está o queGNU sed
faz:
echo foo | sed 'i\
This line starts with spaces.'
Saída:
This line starts with spaces.
foo