Como adicionar novas linhas ao usar eco


42

Por que o comando a seguir não insere novas linhas no arquivo gerado e qual é a solução?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2

6
É echoobrigatório? você pode usar printf.
Archemar 30/07/2015

Eu não sabia sobre printf, com printf funciona: P ... então o que faz com que não funcione com eco então?
Saeid Yazdani

É \rincluir na saída ou faz parte da CRLFnova linha?
cuonglm

9
Existem muitas implementações de echocomando diferentes incompatíveis entre si. Portanto, é recomendável usar uma ferramenta mais padrão como printf. Consulte unix.stackexchange.com/questions/65803/… para obter uma visão geral mais detalhada do problema.
jimmij

Respostas:


38

echo


Uma echoimplementação que esteja em conformidade estrita com a Especificação Unix Única adicionará novas linhas se você:

echo 'line1\nline2'

Mas esse não é um comportamento confiável. Na verdade, não há realmente não é qualquer comportamento padrão que você pode esperar de echo.

OPERANDO

string

Uma sequência a ser gravada na saída padrão. Se o primeiro operando for -n, ou se algum dos operandos contiver um caractere < \barra invertida> , os resultados serão definidos pela implementação .

Nos sistemas em conformidade com XSI , se o primeiro operando for -n, ele deve ser tratado como uma sequência, não como uma opção . As seguintes seqüências de caracteres devem ser reconhecidas em sistemas compatíveis com XSI em qualquer um dos argumentos:

\a- Escreva um <alerta> .

\b- Escreva um <backspace> .

\c- Suprima o <newline> que segue o argumento final na saída. Todos os caracteres que seguem \cos argumentos devem ser ignorados.

\f- Escreva um <formfeed> .

\n- Escreva um <newline> .

\r- Escreva um <retorno de carro> .

\t- Escreva uma <tab> .

\v- Escreva uma <vertical-tab> .

\\- Escreva um caractere <barra invertida> .

\0num- Escreva um valor de 8 bits que seja o número octal de zero, um, dois ou três dígitos num.

E, portanto, realmente não existe uma maneira geral de saber como escrever uma nova linha echo, exceto que geralmente você pode confiar apenas echoem fazê-lo.

Um bashshell normalmente não está em conformidade com a especificação e lida com as -noutras opções, mas mesmo isso é incerto. Você pode fazer:

shopt -s xpg_echo
echo hey\\nthere

hey
there

E nem isso é necessário se bashtiver sido construído com a opção de tempo de compilação ...

--enable-xpg-echo-default

Faça o echobuilt-in expandir caracteres de escape com barra invertida por padrão, sem exigir a -eopção. Isso define o valor padrão da xpg_echoopção shell para on, o que faz com que o Bash echose comporte mais como a versão especificada na Especificação Unix Única, versão 3. Consulte Bash Builtins , para obter uma descrição das seqüências de escape que echoreconhecem.


printf


Por outro lado, printfo comportamento é bastante manso em comparação.

JUSTIFICATIVA

O printfutilitário foi adicionado para fornecer funcionalidades historicamente fornecidas por echo. No entanto, devido a diferenças irreconciliáveis nas várias versões echoexistentes, a versão possui poucos recursos especiais, deixando-os para este novo printfutilitário, baseado em um sistema da Nona Edição.

A seção DESCRIÇÃO ESTENDIDA corresponde quase exatamente à printf()função no padrão ISO C, embora seja descrita em termos da notação de formato de arquivo na Notação de formato de arquivo XBD .

Ele lida com strings de formato que descrevem seus argumentos - que podem ser inúmeras coisas, mas para strings são basicamente %bstrings yte ou strings literais %s. Além dos %formats no primeiro argumento, ele se comporta mais como um %bargumento de string yte, exceto pelo fato de não lidar com a \cfuga.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Consulte Por que é printfmelhor que echo? para mais.


echo() printf


Você pode escrever seus próprios padrões conforme echo...

echo(){
    printf '%b ' "$@\n\c"
}

... o que deve sempre fazer a coisa certa automaticamente.

Na verdade, não ... Isso imprime um literal \nno final dos argumentos se o último argumento terminar em um número ímpar de <barras invertidas> .

Mas isso não acontece:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac

+1 para a shopt -s xpg_echoopção echousada -epor padrão.
Vignesh Raja

Esta solução não funciona sem -e. Estou surpreso que ninguém percebeu isso, exceto talvez @HaydeSchiff
ha9u63ar

@ ha9u63ar - uhh ... você leu isso?
mikeserv 03/10

27

Passe o sinalizador -e para ecoar para analisar caracteres escapados, como "\ r \ n", da seguinte maneira:

echo -e "Line 1\r\nLine2" >> readme.txt

Uma opção "-e" simples e agradável para que as seqüências de escape funcionem - diz outra resposta que echonão é confiável e não segue padrões diferentes printf.
Edward

1
Verifique se o seu roteiro não contém qualquer literal \ r \ n, como em um tr -d "\n"comando.
Novmen

8

Em todas as versões do bash que usei, você pode simplesmente inserir uma nova linha literal em uma sequência de forma interativa ou em um script, desde que a sequência seja suficientemente citada.

Interativamente:

$ echo "Line one
> Line two"
Line one
Line two
$

Em um script:

echo "Line one
Line two"

4
echo -e "Line 1\r\nLine2" >> readme.txt

outras possibilidades de uso:

man echo

2

As pessoas já responderam adequadamente, mas eu me recuso a aceitar um mundo onde o eco aceita qualquer outra opção que não seja -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3

1

Se você tem um personagem que não faz parte da mensagem, pode passar por sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.