web-dev-qa-db-fra.com

Comment ajouter des sauts de ligne dans des variables dans le script bash

Quand je fais

str="Hello World\n===========\n"

Je reçois le \n imprimé aussi. Comment puis-je avoir des nouvelles lignes?

80
Jiew Meng

Dans bash vous pouvez utiliser la syntaxe

str=$'Hello World\n===========\n'

Citations simples précédées d'un $ est une nouvelle syntaxe qui permet d'insérer des séquences d'échappement dans des chaînes.

printf intégré permet également d'enregistrer la sortie résultante dans une variable

printf -v str 'Hello World\n===========\n'

Les deux solutions ne nécessitent pas de sous-shell.

Si, dans ce qui suit, vous devez imprimer la chaîne, vous devez utiliser des guillemets doubles, comme dans l'exemple suivant:

echo "$str"

car lorsque vous imprimez la chaîne sans guillemets, la nouvelle ligne est convertie en espaces.

90
enzotib

Vous pouvez mettre des sauts de ligne littéraux entre guillemets simples (dans n'importe quel shell de style Bourne/POSIX).

str='Hello World
===========
'

Pour une chaîne multiligne, ici les documents sont souvent pratiques. La chaîne est introduite en entrée d'une commande.

mycommand <<'EOF'
Hello World
===========
EOF

Si vous souhaitez stocker la chaîne dans une variable, utilisez la commande cat dans une substitution de commande. Le ou les caractères de nouvelle ligne à la fin de la chaîne seront supprimés par la substitution de commande. Si vous souhaitez conserver les nouvelles lignes finales, placez un bouchon à la fin et retirez-le ensuite. Dans les shells compatibles POSIX, vous pouvez écrire str=$(cat <<'EOF'); str=${str%a} suivi de l'heredoc proprement dit, mais bash requiert que l'heredoc apparaisse avant la parenthèse fermante.

str=$(cat <<'EOF'
Hello World
===========
a
EOF
); str=${str%a}

Dans ksh, bash et zsh, vous pouvez utiliser le formulaire entre guillemets $'…' Pour développer les échappements antislash à l'intérieur des guillemets.

str=$'Hello World\n===========\n'

Utilisez-vous "echo"? Essayez "echo -e".

echo -e "Hello World\n===========\n"
9
Mike

Si vous avez besoin de plusieurs sauts de ligne dans votre script, vous pouvez déclarer une variable globale contenant un saut de ligne. De cette façon, vous pouvez l'utiliser dans des chaînes entre guillemets doubles (extensions variables).

NL=$'\n'
str="Hello World${NL} and here is a variable $PATH ===========${NL}"
6
pihentagy

Pour compléter les grandes réponses existantes:

Si vous utilisez bash et que vous préférez en utilisant des sauts de ligne réels pour la lisibilité, read est une autre option pour capturer un ici-doc dans une variable, qui (comme d'autres solutions ici) ne nécessite pas l'utilisation d'un sous-shell.

# Reads a here-doc, trimming leading and trailing whitespace.
# Use `IFS= read ...` to preserve it (the trailing \n, here).
read -r -d '' str <<'EOF'   # Use `IFS= read ...` to preserve the trailing \n
Hello World
===========
EOF
# Test: output the variable enclosed in "[...]", to show the value's boundaries.
$ echo "$str"
[Hello World
===========]
  • -r garantit que read n'interprète pas l'entrée (par défaut, elle traiterait les antislashs spéciaux, mais cela est rarement nécessaire).

  • -d '' définit le délimiteur "record" sur une chaîne vide, ce qui oblige read à lire l'entrée entière à la fois (au lieu d'un simple une seule ligne).

Notez qu'en quittant $IFS (le séparateur de champ interne) par défaut, $' \t\n' (un espace, une tabulation, une nouvelle ligne), tout espace blanc de début et de fin est coupé de la valeur affectée à $str, qui inclut la nouvelle ligne de fin de l'ici-doc.
(Notez que même si le corps du document ici commence sur la ligne après le délimiteur de début ('EOF' ici), il ne contient pas un début nouvelle ligne).

Habituellement, c'est le comportement souhaité, mais si vous voulez ce retour à la ligne, utilisez IFS= read -r -d '' au lieu de simplement read -r -d '', mais notez que tout espace blanc de début et de fin est alors conservé.
(Notez que le préfixe IFS=  directement à la commande read signifie que l'affectation n'est effective que pendant cette commande, il n'est donc pas nécessaire de restaurer la valeur précédente.)


L'utilisation d'un here-doc vous permet également de éventuellement utiliser l'indentation pour définir la chaîne multiligne pour la lisibilité:

# Caveat: indentation must be actual *tab* characters - spaces won't work.
read -r -d '' str <<-'EOF' # NOTE: Only works if the indentation uses actual tab (\t) chars.
    Hello World
    ===========
EOF
# Output the variable enclosed in "[...]", to show the value's boundaries.
# Note how the leading tabs were stripped.
$ echo "$str"
[Hello World
===========]

Placement - entre << et le délimiteur d'ouverture ici-doc ('EOF', ici) entraîne la suppression des caractères de tabulation du corps du document ici et même du délimiteur de fermeture, mais notez que cela ne fonctionne qu'avec réel tabulations, pas d'espaces, donc si votre éditeur traduit les touches de tabulation en espaces, un travail supplémentaire est nécessaire.

3
mklement0

De toute discussion, voici le moyen le plus simple pour moi:

bash$ str="Hello World
==========="
bash$ echo "$str"
Hello World
===========

La commande echo doit utiliser guillemets doubles.

3
kholis