Pourquoi une chaîne bash ici ajoute-t-elle un caractère de fin de nouvelle ligne?

34

Les exemples suivants montrent qu'une nouvelle ligne est ajoutée à une chaîne here .
Pourquoi est-ce fait?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a
Peter.O
la source

Réponses:

38

La réponse facile est que ksh est écrit de cette façon (et bash est compatible). Mais il y a une raison pour ce choix de conception.

La plupart des commandes attendent une saisie de texte. Dans le monde Unix, un fichier texte consiste en une séquence de lignes, chacune se terminant par une nouvelle ligne . Donc, dans la plupart des cas, une nouvelle ligne finale est requise. Un cas particulièrement courant consiste à récupérer le résultat d’une commande avec une substitution de commande, à le traiter d’une manière ou d’une autre, puis à le transmettre à une autre commande. La substitution de commande supprime les nouvelles lignes finales; <<<en remet un.

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

Bash et ksh ne peuvent de toute façon pas manipuler les données binaires (ils ne peuvent pas gérer les caractères nuls), il n’est donc pas étonnant que leurs installations soient conçues pour les données texte.

La <<<syntaxe here-string est de toute façon principalement pratique, comme <<ici-documents. Si vous ne devez pas ajouter de nouvelle ligne finale, utilisez echo -n(en bash) ou printfet un pipeline.

Gilles, arrête de faire le mal
la source
Beaucoup plus approfondi que ma réponse.
Mike
2
Bash peut avoir emprunté ici cordes de ksh93, mais ksh à son tour les empruntés à zsh, qui les a de la coquille Plan 9 rc .
Mark Reed
2
<<<a été introduit dans le monde Bourne par zsh, pas ksh. Et il a été inspiré par un opérateur similaire dans le port Unix rcauquel il n’a pas ajouté ce caractère de nouvelle ligne supplémentaire. Fait intéressant, l' =(<<<text)opérateur n'ajoute pas cette nouvelle ligne dans zsh.
Stéphane Chazelas
Si vous vous interrogez sur l'intérêt de cette réponse, c'est à cause de cette question dans SO .
fedorqui
1
Existe-t-il un moyen d'écrire la chaîne here (sans utiliser d'autre utilitaire tel que printf, etc.) en évitant le retour à la ligne bash? Comme @ StéphaneChazelas pointé est possible dans zsh.
CTodea
3

Un scénario dans lequel il est pratique d’ajouter des nouvelles lignes à ces chaînes est lors de l’utilisation de la readcommande lorsque le set -emode est actif. Rappelez-vous qu'un set -escript se termine lorsqu'il rencontre (plus ou moins) des instructions générant un code d'état différent de zéro. Considérez que readgénère un code de statut différent de zéro lorsqu'il rencontre une chaîne sans saut de ligne:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'
Dejay Clayton
la source
-3

Je pense que c'est le seul moyen d'obtenir une nouvelle ligne à la fin d'une chaîne ici, la preuve:

xxd <<<`echo -ne "a\n"`

Il semblerait que l'opérateur here-string supprime les nouvelles lignes sauf si elles sont spécifiées dans la syntaxe que vous avez soumise.

Mike
la source
4
C'est la substitution de commande qui supprime la nouvelle ligne finale. Vous pouvez simplifier cela xxd <<<$(echo a).
Gilles 'SO- arrête d'être méchant'