it-swarm-eu.dev

Jak přidat nové řádky do proměnných v bash skriptu

Když dělám

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

Dostanu \n vytištěno také. Jak tedy mohu mít nové řádky?

80
Jiew Meng

V bash můžete použít syntaxi

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

Jednotlivé nabídky, kterým předchází $ je nová syntaxe, která umožňuje vkládat escape řetězce do řetězců.

Také zabudovaný printf umožňuje uložit výsledný výstup do proměnné

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

Obě řešení nevyžadují subshell.

Pokud v následujícím textu potřebujete vytisknout řetězec, měli byste použít dvojité uvozovky, jako v následujícím příkladu:

echo "$str"

protože při tisku řetězce bez uvozovek se nový řádek převede na mezery.

90
enzotib

Do jediných uvozovek můžete vložit doslovné řádky (v jakémkoli stylu Shell Bourne/POSIX).

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

Pro víceřádkový řetězec jsou často zde dokumenty . Řetězec je přiváděn jako vstup do příkazu.

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

Pokud chcete řetězec uložit do proměnné, použijte příkaz cat v substituci příkazu. Znaky nového řádku na konci řetězce budou odstraněny nahrazením příkazu. Pokud si chcete zachovat poslední řádky, položte na konec zátku a poté ji odtáhněte. V shellech kompatibilních s POSIXem můžete napsat str=$(cat <<'EOF'); str=${str%a} následovaný vlastním heredocem, ale bash vyžaduje, aby se heredoc objevil před závěrečnou závorkou.

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

V ksh, bash a zsh můžete pomocí citovaného formuláře $'…' Rozbalit úniky zpětného lomítka uvnitř uvozovek.

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

Používáte echo? Zkuste "echo -e".

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

Pokud potřebujete ve svém skriptu nové řádky mnohokrát, můžete deklarovat globální proměnnou obsahující nový řádek. Tímto způsobem ji můžete použít ve dvojitě uvězněných řetězcích (variabilní rozšíření).

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

Doplnění skvělých existujících odpovědí:

Pokud používáte bash a dáváte přednost použití aktuálních nových řádků pro čitelnost, read je další možnost pro zachycení here-doc v proměnné, což (stejně jako jiná řešení zde) nevyžaduje použití podshell.

# 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 zajišťuje, že read neinterpretuje vstup (ve výchozím nastavení by zacházelo se speciálními zpětnými lomítky, ale to je zřídka nutné).

  • -d '' nastaví oddělovač „záznamu“ na prázdný řetězec, což způsobí, že read přečte celý celý vstup najednou (namísto pouze jednoho řádku).

Všimněte si, že ponecháním $IFS (interní oddělovač pole) ve výchozím nastavení, $' \t\n' (mezera, karta, nový řádek), jakýkoli úvodní a koncový mezera je oříznut z hodnoty přiřazené $str, která obsahuje koncový nový řádek here-doc.
(Všimněte si, že i když se tělo tohoto dokumentu začíná na řádku za oddělovačem začátku ('EOF' zde), neobsahuje úvodní úvodní nový řádek).

Obvykle se jedná o požadované chování, ale pokud chcete, aby koncové řádky, použijte IFS= read -r -d '' místo pouhého read -r -d '', ale uvědomte si, že je zachován jakýkoli úvodní a koncový mezerník.
(Všimněte si, že se připravuje IFS=  přímo k příkazu read znamená, že přiřazení platí pouze během tohoto příkazu, takže není třeba obnovit předchozí hodnotu.)


Použití dokumentu Here-doc také umožňuje volitelně použít odsazení a nastavit víceřádkový řetězec pro čitelnost:

# 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
===========]

Umístění - mezi << a oddělovač zde-doc ('EOF', zde) způsobuje, že vedoucí znaky tabulátoru budou odstraněny z těla here-doc a dokonce i oddělovače, ale nezapomeňte, že tato funguje pouze s skutečnou kartou postavy, nikoli mezery, takže pokud váš editor překládá klávesové zkratky na kartě do mezer, je zapotřebí další práce.

3
mklement0

Ze všech diskusí je pro mě nejjednodušší způsob:

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

Příkaz echo musí používat dvojité uvozovky.

3
kholis