Selon l'exemple suivant, et comme dans ma récente question Dans bash, où est passé le caractère de fin de ligne? , Je veux savoir "pourquoi" ça arrive
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p
# Output is: 610a62
# The trailing newline from the 'echo' command
# has been "deleted" by Command Substitution
Je suppose qu'il doit y avoir une raison très importante pour une action shell, à savoir la substitution de commande, de supprimer réellement certaines données de la sortie de commande qu'elle remplace ...
mais je ne peux pas me concentrer sur celle-ci, car il semble que ce soit l'antithèse de ce qu'il est censé faire .. ie. pour passer la sortie d'une commande dans le processus de script ... Retenir un caractère me semble bizarre, mais je suppose qu'il y a une raison raisonnable à cela ... Je suis impatient de savoir quelle est cette raison .. .
Réponses:
Parce que le shell n'était pas à l'origine destiné à être un langage de programmation complet.
Il est assez difficile de supprimer une fin
\n
d'une sortie de commande. Cependant, à des fins d'affichage, presque toutes les commandes terminent leur sortie par\n
, donc ... il doit y avoir un moyen simple de le supprimer lorsque vous souhaitez l'utiliser dans une autre commande. Le retrait automatique avec la$()
construction a été la solution choisie.Alors, vous accepterez peut-être cette question comme réponse:
Pouvez-vous trouver un moyen simple de supprimer la fin
\n
si cela n'a pas été fait automatiquement dans la commande suivante?Notez que les guillemets sont nécessaires pour éviter de casser les espaces doubles qui peuvent apparaître dans les dates formatées.
la source
shopt
pour changer votre comportement par défaut décrit, alors je serais à nouveau heureux ... Je trouve difficile de penser que Bash / Linux / Unix polluerait une fonction aussi critique que "capturer stdout" juste parce qu'elledate
n'a pas une option avec / sans '\ n' ... La solution évidente serait que bash (ou un autre shell) ait unshopt
pour cela ... En connaissez-vous? .. et avez-vous des liens de référence qui parlent du pourquoi et du pourquoi de ce problème? ... et pourquoi n'a pasdate
d'option \ n .. Ça devrait!$()
syntaxe alternative préférée .{ echo -n "The current date is "; var="$(date; echo -e x)"; var="${var%x}"; echo -n "$var"; echo ", have a good day!"; }
.. alors qu'il soit :)date
cela fonctionnerait, mais je viens de l'utiliserdate
comme exemple de toute commande ..Cela fait partie de la norme :
Bien sûr, la norme est probablement écrite de cette façon parce que c'est comme
ksh
ça ou quelque chose, mais c'est la norme, et c'est un comportement documenté. Si vous ne l'aimez pas, utilisez Perl ou autre chose qui vous permettra de conserver les nouvelles lignes de fin.la source
Eh bien, cela a du sens pour moi. La nouvelle ligne n'est là qu'en premier lieu, dans la sortie de commande normale, de sorte que l'invite s'affiche une fois la commande terminée sur une nouvelle ligne. La nouvelle ligne ne fait pas partie de la sortie d'origine dans la plupart des cas, elle est là pour ranger l'écran. Lorsque vous analysez la sortie d'une commande, la nouvelle ligne à la fin est généralement gênante. Pourquoi la
wc
commande génère-t-elle 2 lignes de texte? Oh, ce n'est pas le cas, il en génère un suivi d'une nouvelle ligne. Lorsque vous analysez,wc
vous ne voulez pas vous inquiéter du fait qu'il y a 2 lignes de sortie - il n'y en a pas vraiment, il n'y en a qu'une.la source
\n
dans lestdout
flux d' origine est supprimé par la substitution de commande. c'est à dire. mes nouvelles données (données très importantes) ont des retours à la ligne supprimés, même lorsque les données sont entourées de "guillemets". Je comprends raisonnablement comment et pourquoi le fractionnement de mots fonctionne, mais je ne sais absolument pas pourquoi la substitution de commandes supprime uniquement les nouvelles lignes et les seules lignes de fin .Je rencontrais le même problème et j'ai trouvé l'exemple ci-dessous. Il semble que la citation ait aidé la situation, du moins pour moi:
http://tldp.org/LDP/abs/html/commandsub.html .
la source
$str
, contenant la chaîne"a b c"
. Si vous passez$str
àecho
sans les guillemets (echo $str
),echo
recevraa
,b
etc
que trois arguments distincts. Votre shell ne se soucie pas de l'espace entre les arguments.echo
affichera ensuite ces arguments avec des espaces séparant chacun, donc vous obtenez"a b c"
. Si vous passez la variable àecho
avec des guillemets autour d'elle (echo "$str"
), le shell la voit comme un argument et laecho
reçoit en tant que telle, donc le blanc n'est pas réduit. Il en va de même pour les nouvelles lignes.-n
drapeau ne soit passé ,echo
ajoute une nouvelle ligne de fin à sa sortie, donc les deux échos de votre exemple ont des nouvelles lignes de fin. Cependant, si vous essayezecho -n $dir_listing
ouecho -n "$dir_listing"
, vous verrez qu'aucun retour à la ligne de fin n'est imprimé avec ou sans guillemets$dir_listing
, ce qui suggère que le problème vient de la substitution de commande.pourquoi
echo "hello "
(sans les guillemets) engloutit l'espace? la valeur des caractères IFS est vue par le shell comme étant des délimiteurs, donc les derniers (qui ne délimitent rien) sont supprimés. la substitution de commend consiste simplement à exécuter les commends dans un sous-shell, elle suit donc la même logique.la source
x="hello "
etx="hello "
perdront tous leurs espaces de fin s'ils sont affichés viaecho $x
... Cependant, seule la toute dernière nouvelle ligne de la Substitution de commande est perdue.IFS
n'a rien à voir avec la suppression des sauts de ligne à la fin des substitutions de commande.