Eu tenho uma string que contém caracteres de nova linha. Quero escapar de todas as novas linhas nessa sequência, substituindo todos os caracteres de nova linha por uma sequência de dois caracteres: "\n". Como posso fazer isso no POSIX sh?
Aqui está o objetivo:
$ printf 'a\nb\nc\nd' | escape_newlines | od -a
0000000 a \ n b \ n c \ n d
141 134 156 142 134 156 143 134 156 144
0000012
Como posso definir escape_newlines
?
Métodos que tentei:
tr
— Problema: não é possível converter um único caractere em vários caracteres.awk 'BEGIN{ORS="\\n"} {print}'
— Problema: sempre insere a string de dois caracteres "\n" no final da string, mesmo que a string não termine com um caractere de nova linha. Exemplo:$ printf 'hi\n' | awk 'BEGIN{ORS="\\n"} {print}' | od -ab 0000000 h i \ n 150 151 134 156 0000004 $ printf 'hi' | awk 'BEGIN{ORS="\\n"} {print}' | od -ab 0000000 h i \ n 150 151 134 156 0000004
sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g'
— Problema: se houver um caractere de nova linha no final da string, ele não será convertido. Exemplo:$ printf 'h\ni' | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g' | od -ab 0000000 h \ n i 150 134 156 151 0000004 $ printf 'h\ni\n' | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g' | od -ab 0000000 h \ n i nl 150 134 156 151 012 0000005
Experimente
awk
com:Em qualquer caso, observe que a substituição do comando remove todos os caracteres de nova linha finais. OK aqui, pois a saída de
awk
não contém nenhum, mas isso significa que também poderíamos ter usadoprint
em vez deprintf "%s"
.Com
sed
:Observe que, por POSIX, usar
N
na última linha destina-se a descartar o espaço padrão e sair. GNUsed
só faz isso quando$POSIXLY_CORRECT
está no ambiente, mas ainda sai quandoN
chamado na última linha (mas ainda imprime o espaço padrão).Usamos
LC_ALL=C
para evitar possíveis problemas com a decodificação da string no charmap da localidade do usuário.sed
é um utilitário de texto, portanto espera entrada de texto e produz saída de texto. Algo que não está vazio e não termina com um caractere de nova linha não é texto. Aqui adicionamos uma nova linha à entrada e contamos com a substituição do comando para remover aquelased
adicionada na saída.Observe também que se a entrada tiver linhas com comprimento em bytes maior que LINE_MAX (que pode ser tão baixo quanto 1024), isso também a tornará não-texto e o comportamento não será especificado. IIRC, o espaço padrão também não é necessário para conter mais de 10 x LINE_MAX.
A
awk
abordagem também terá alguns limites começando com ARG_MAX que nos sistemas será inferior a 10 x LINE_MAX.Não há limite para o tamanho de uma variável shell, embora se ela for exportada para o ambiente, ela será executada no limite ARG_MAX para todos os comandos externos executados.
Para processar um stream, você precisaria de algo como:
Embora esteja ciente de que a saída não é texto, portanto não pode ser processada por um utilitário de texto POSIX.