bashスクリプトの変数に改行を追加する方法


64

私がする時

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

私も\n印刷されます。どうすれば改行ができますか?


1
ここでの答えは素晴らしいですが、実際には、ほとんどの場合、この種のことのために配列を使用する方が良いと思います。
evilsoup

回答:


73

bash構文を使用できます

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

a $で始まる単一引用符は、文字列にエスケープシーケンスを挿入できる新しい構文です。

また、printfビルトインにより、結果の出力を変数に保存できます

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

どちらのソリューションもサブシェルを必要としません。

以下で文字列を印刷する必要がある場合は、次の例のように二重引用符を使用する必要があります。

echo "$str"

引用符なしで文字列を印刷すると、改行がスペースに変換されるためです。


1
構文は何とstr=$'Hello World\n===========\n'呼ばれますか?変数置換?
zengr

5
@zengr:ANSI-C引用と呼ばれ、andでもサポートされzshていkshます; ただし、POSIX準拠ではありません。
mklement0

4
@ mkelement0、それはは、ksh93から来て、またzshのは、bash、mkshとFreeBSDのSHによってサポートされている、およびPOSIXの次のメジャーリビジョンでの含めることはある議論の下で
ステファンChazelas

1
二重引用符で動作しないようですか?例えばstr=$"My $PET eats:\n$PET food"このアプローチは二重引用符で機能します
Brad Parks

31

リテラルの改行を一重引用符で囲むことができます(Bourne / POSIXスタイルのシェルで)。

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

複数行の文字列の場合、here文書はしばしば便利です。文字列はコマンドへの入力として供給されます。

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

文字列を変数に保存する場合catは、コマンド置換でコマンドを使用します。文字列の末尾の改行文字は、コマンド置換によって削除されます。最終的な改行を保持したい場合は、最後にストッパーを付けて、後で取り除きます。POSIX準拠のシェルでは、str=$(cat <<'EOF'); str=${str%a}適切なheredocを続けて記述できますが、bashでは、閉じ括弧の前にheredocが必要です。

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

ksh、bash、zshでは、$'…'引用符で囲まれた形式を使用して、引用符内のバックスラッシュエスケープを展開できます。

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

1
私は、GNUのbashの4.1.5を使っていて、str=$(cat <<'EOF')そのままでは動作しません。.. )ニーズがエンドの-docの後に次の行に配置するEOF..しかし、たとえそうであっても、それはコマンドによる末尾の改行を失います置換。
Peter.O

@fred良い点、末尾の改行について説明し、bashで動作するコードを示しました。これはbashのバグだと思いますが、正直に言うと、POSIX仕様を読み直したときに、<<がコマンド置換内にあり、heredocがそうでない場合に動作が必須であることは不明です。
ジル 'SO-悪であるのをやめる'

素晴らしいもの; 変数でhere-docをキャプチャするときに末尾(および先頭)の\nインスタンスを保持するには、ストッパーアプローチの代替手段としてbash検討IFS= read -r -d '' str <<'EOF'...してください(私の回答を参照)。
mklement0 14

8

「エコー」を使用していますか?「echo -e」を試してください。

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

2
ところで。echo-nを指定しない限り、最後の\ n は自動的に追加されるため、最後の\ nは必要ありません。(ただし、問題の主な問題は、これらの改行を変数に入れる方法です)。
Peter.O

+1すべてのソリューションの中で、これは最も直接的で最も簡単なソリューションです。
ハイVuの

エコー-eがOS Xで動作しない
グレッグM.クルサック14

2
@GregKrsak:ではbashecho -e OS X上で動作する-ためですecho、bashのある組み込み(むしろ外部実行可能ファイルより)、その組み込みがサポートしています-e。(組み込みとして、それは上で動作する必要があり、すべてのbashが稼働プラットフォーム;ちなみに、echo -eで動作kshし、zshあまりにも)。ただし、対照的に、 OS Xの外部echoユーティリティ/bin/echo-をサポートしていませ-e
mklement0 14

4

スクリプトで改行を何度も必要とする場合、改行を保持するグローバル変数を宣言できます。そうすれば、二重引用符で囲まれた文字列(変数展開)で使用できます。

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

なぜ$''サブシェルが必要なのですか?
マット

申し訳ありませんが、答えを読み違えました。
pihentagy

ダウンボッターからの説明をお願いできますか?
-pihentagy

いいね!これは例えば、二重引用符を使用して変数に含めることができます"My dog eats:${NL}dog food"
ブラッド・パークス

これは私のために働いた。bashスクリプトを使用して、クリップボードに自動的にコピーされる文字列を合成し、後で他の場所に貼り付ける場合、このアプローチは結果の出力に改行を追加するために機能しました。
ヴィル

3

すべての議論から、これが私にとって最も簡単な方法です:

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

エコーコマンドを使用する必要があり、二重引用符を


3

既存の優れた答えを補完するには:

あなたが使用している場合bash、あなたが好む読みやすくするために、実際の改行を使用してreadために別のオプションである変数にここ-docのキャプチャサブシェルの使用を必要としない(ここでは他のソリューションなど)、。

# 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
===========]
  • -rread入力を解釈しないことを保証します(デフォルトでは、バックスラッシュを特別に扱いますが、それはめったに必要ありません)。

  • -d ''「レコード」区切り文字を空の文字列に設定し、入力全体を(1行だけでなく)一度readに読み取ります。

$IFS(内部フィールド区切り文字)をデフォルト$' \t\n'(スペース、タブ、改行)のままにしておく$str、ヒアドキュメントの末尾の改行を含むに割り当てられた値から先頭および末尾の空白が削除されることに注意してください。
(here-docの本文は開始区切り文字(ここ)のの行から始まりますが、先頭の改行含まれ'EOF'ていませ)。

通常、これは望ましい動作ですが、末尾の改行が必要な場合IFS= read -r -d ''は、justの代わりに使用しますが、先頭および末尾の空白は保持さread -r -d ''れることに注意してください。
(コマンドの前にIFS= 直接追加することreadは、そのコマンドの間のみ割り当てが有効になることを意味するため、前の値を復元する必要はありません。)


here-docを使用すると、オプションでインデント使用して読みやすくするために複数行の文字列を設定できます。

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

here-docの区切り記号(、ここ)の-間に配置する<<と、'EOF'先行するタブ文字がhere-docの本文から、さらには区切り記号からも削除されますが、スペースではなく実際のタブ文字のみ機能することに注意してください。エディターは、タブキーをスペースに変換します。追加の作業が必要です。


-1

次のように行う必要があります。

STR=$(echo -ne "Hello World\n===========\n")

更新:

フレッドが指摘したように、この方法で末尾の「\ n」を失うことになります。バックスラッシュシーケンスを展開して変数を割り当てるには、次のようにします。

STR=$'Hello World\n===========\n\n'

テストしてみましょう:

echo "[[$STR]]"

今私たちに与えます:

[[Hello World
===========

]]

$ ''は$ ""とは異なることに注意してください。2番目は、現在のロケールに従って翻訳を行います。詳細については、「QUOTING」セクションを参照してくださいman bash


-2
#!/bin/bash

result=""

foo="FOO"
bar="BAR"

result+=$(printf '%s' "$foo")$'\n'
result+=$(printf '%s' "$bar")$'\n'

echo "$result"
printf '%s' "$result"

出力:

FOO
BAR

FOO
BAR

1
なぜ単純ではないのですresult+=$foo$'\n'か?$(printf %s "$foo")末尾の改行文字がある$foo場合、それをトリミングします。
ステファンシャゼラス16

コードについての説明はありませんが、それ以外の場合は問題ありません。
somethingSomething
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.