Comment ajouter de nouvelles lignes en utilisant echo

42

Pourquoi la commande suivante n'insère-t-elle pas de nouvelles lignes dans le fichier généré et quelle est la solution?

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

$ cat readme.txt 
Line 1\r\nLine2
Saeid Yazdani
la source
6
Est-ce echoobligatoire? vous pouvez utiliser printf.
Archemar
Je ne connaissais pas printf, avec printf ça marche: P ... alors qu'est-ce que ça fait de ne pas travailler avec echo alors?
Saeid Yazdani
Est-ce que \rinclude est inclus ou fait-il partie de CRLFnewline?
jeudi
9
Il existe de nombreuses implémentations de echocommande incompatibles les unes avec les autres. Ainsi, il est recommandé d'utiliser un outil plus standard comme printf. Voir unix.stackexchange.com/questions/65803/… pour une vue d'ensemble du problème.
jimmij
En cas de dépassement de pile, Echo newline in Bash imprime littéralement \ nLa nouvelle ligne Echo in Bash imprime littéralement \ n a quelques réponses utiles.
Graham Perrin

Réponses:

38

echo


Une echoimplémentation strictement conforme à la spécification Single Unix ajoutera de nouvelles lignes si vous:

echo 'line1\nline2'

Mais ce n'est pas un comportement fiable. En fait, il vraiment ne importe quel comportement standard que vous pouvez attendre de echo.

OPERANDS

string

Une chaîne à écrire sur la sortie standard. Si le premier opérande est -nou si l'un des opérandes contient un caractère < \barre oblique inverse> , les résultats sont définis par l'implémentation .

Sur les systèmes conformes à XSI , si le premier opérande est -n, il doit être traité comme une chaîne et non comme une option . Les séquences de caractères suivantes doivent être reconnues sur les systèmes conformes à XSI dans tous les arguments:

\a- Ecrivez une <alerte> .

\b- Ecrivez un <backspace> .

\c- Supprimez la <nouvelle ligne> qui suit sinon le dernier argument de la sortie. Tous les caractères suivant les \carguments doivent être ignorés.

\f- Ecrivez un <formulaire> .

\n- Ecrivez une <nouvelle ligne> .

\r- Ecrivez un <retour-chariot> .

\t- Ecrivez un <tab> .

\v- Ecrivez un <vertical-tab> .

\\- Écrivez un caractère <barre oblique inverse> .

\0num- Écrivez une valeur sur 8 bits représentant le nombre octal zéro, un, deux ou trois chiffres num.

Et donc il n’existe vraiment aucun moyen général de savoir écrire une nouvelle ligne echo, si ce n’est que vous pouvez généralement vous fier echoà cela.

Un bashshell n’est généralement pas conforme à la spécification et gère les -noptions, ainsi que d’autres options, mais même cela reste incertain. Tu peux faire:

shopt -s xpg_echo
echo hey\\nthere

hey
there

Et même pas nécessaire si basha été construit avec l'option de construction ...

--enable-xpg-echo-default

Faites en echosorte que les caractères intégrés par défaut utilisent une barre oblique inversée par défaut, sans nécessiter d’ -eoption. Ceci définit la valeur par défaut de l' xpg_echooption shell sur on, ce qui permet au echocomportement de Bash de se comporter davantage comme la version spécifiée dans Single Unix Specification, version 3. Pour plus d'informations sur les séquences d'échappement reconnues , voir Bash Builtinsecho .


printf


Par contre, printfle comportement de ce dernier est assez docile en comparaison.

RAISONNEMENT

L' printfutilitaire a été ajouté pour fournir une fonctionnalité qui a toujours été fournie par echo. Cependant, en raison de différences irréconciliables entre les différentes versions d’ echoexistant, la version présente peu de fonctionnalités spéciales, ce qui les laisse à ce nouvel printfutilitaire, qui est basé sur celui du système Ninth Edition.

La section DESCRIPTION EXTENDUE correspond presque exactement à la printf()fonction de la norme ISO C, bien qu'elle soit décrite en termes de notation de format de fichier dans la notation de format de fichier XBD .

Il gère les chaînes de format qui décrivent ses arguments - ce qui peut être n'importe quel nombre de choses, mais les chaînes sont en %bgros des chaînes yte ou des chaînes littérales %s. À part les %formats dans le premier argument, il se comporte presque comme un %bargument de chaîne yte, sauf qu'il ne gère pas l' \céchappement.

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

^
\n$^    \t$

Voir Pourquoi est printfmeilleur que echo? pour plus.


echo() printf


Vous pourriez écrire vos propres normes conformes echocomme ...

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

... ce qui devrait presque toujours faire la bonne chose automatiquement.

En fait, non ... Cela affiche un littéral \nà la fin des arguments si le dernier argument se termine par un nombre impair de <barres obliques inverses> .

Mais cela ne veut pas:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac
Mikeserv
la source
+1 pour l' shopt -s xpg_echooption echoà utiliser -epar défaut.
Vignesh Raja
Cette solution ne fonctionne pas sans -e. Je suis surpris que personne n'ait remarqué cela sauf peut-être @HaydeSchiff
ha9u63ar
@ ha9u63ar - euh ... avez-vous lu ceci?
mikeserv
27

Passez l'indicateur -e à écho pour lui permettre d'analyser les caractères d'échappement tels que "\ r \ n", comme suit:

echo -e "Line 1\r\nLine2" >> readme.txt
Hayden Schiff
la source
Une belle simple option "-e" pour faire fonctionner les séquences d'échappement - cela indique une autre réponse qui echon'est pas fiable et qui ne respecte pas les normes contrairement à ce qui se passe printf.
Edward
1
Assurez-vous que votre script ne contient pas de littéral \ r \ n, comme dans une tr -d "\n"commande.
Noumenon
8

Dans toutes les versions de bash que j'ai utilisées, vous pouvez simplement insérer un saut de ligne littéral dans une chaîne, de manière interactive ou dans un script, à condition que la chaîne soit suffisamment entre guillemets.

De manière interactive:

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

Dans un script:

echo "Line one
Line two"
Trauma numérique
la source
4
echo -e "Line 1\r\nLine2" >> readme.txt

autres possibilités d'utilisation:

man echo
zodo
la source
2

Les gens ont déjà répondu de manière adéquate, mais je refuse d’accepter un monde où écho accepte une option autre que -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3
Staven
la source
1

Si vous avez un personnage qui ne fait pas partie du message, vous pouvez passer à travers 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
très vraisemblable
la source