次のように定義済みのテキストをファイルに書き込みます。
text="this is line one\n
this is line two\n
this is line three"
echo -e $text > filename
私はこのような何かを期待しています:
this is line one
this is line two
this is line three
しかし、これを得ました:
this is line one
this is line two
this is line three
私はそれぞれの\n
の後にスペースがないことを確信しています、しかしどのように余分なスペースが出ますか?
Heredocはこの目的のためにより便利に聞こえます。 ex または cat のようなコマンドインタプリタプログラムに複数のコマンドを送るために使用されます。
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
<<
の後の文字列は、停止する場所を示します。
これらの行をファイルに送信するには、次のようにします。
cat > $FILE <<- EOM
Line 1.
Line 2.
EOM
これらの行を変数に格納することもできます。
read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM
これは行をVAR
という名前の変数に格納します。
印刷するときは、変数を囲む引用符を忘れないでください。そうしないと、改行文字が表示されません。
echo "$VAR"
さらに良いことには、インデントを使ってコードの中でもっと目立つようにすることができます。今度はタブが表示されないようにするために-
の後に<<
を追加するだけです。
read -r -d '' VAR <<- EOM
This is line 1.
This is line 2.
Line 3.
EOM
しかし、その場合は、コード内のインデントのためにスペースではなくタブを使用する必要があります。
あなたが変数に文字列を取得しようとしているなら、もう一つの簡単な方法はこのようなものです:
USAGE=$(cat <<-END
This is line one.
This is line two.
This is line three.
END
)
タブで文字列をインデントすると(つまり '\ t')、インデントは削除されます。スペースでインデントすると、インデントは残ります。
注:最後の閉じ括弧が別の行にあることは、 - - 意味です。 END
のテキストはそれ自身で行に現れなければなりません。
echo
は、渡された引数の間にスペースを追加します。 $text
は変数展開とWord分割の影響を受けるので、echo
コマンドは次のものと同等です。
echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n" ...
"this"の前にスペースが追加されることがわかります。改行文字を削除して、改行を保持するために$text
を引用することができます。
text="this is line one
this is line two
this is line three"
echo "$text" > filename
あるいはprintf
を使用することもできます。これはecho
よりも堅牢で移植性があります。
printf "%s\n" "this is line one" "this is line two" "this is line three" > filename
ブレース展開をサポートしているbash
では、次のようなこともできます。
printf "%s\n" "this is line "{one,two,three} > filename
bashスクリプトでは、次のように動作します。
#!/bin/sh
text="this is line one\nthis is line two\nthis is line three"
echo $text > filename
あるいは:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
cat filenameは次のようになります。
this is line one
this is line two
this is line three
すべての行を適切にインデントしたいので、もっと多くの解決策を見つけました。
echo
を使うことができます:
echo "this is line one" \
"\n""this is line two" \
"\n""this is line three" \
> filename
"\n"
を行末の\
の直前に置いた場合はうまくいきません。
別の方法として、移植性を高めるためにprintf
を使用することもできます(私はecho
に関して多くの問題を抱えていました)。
printf '%s\n' \
"this is line one" \
"this is line two" \
"this is line three" \
> filename
さらに別の解決策があります:
text=''
text="${text}this is line one\n"
text="${text}this is line two\n"
text="${text}this is line three\n"
printf "%b" "$text" > filename
または
text=''
text+="this is line one\n"
text+="this is line two\n"
text+="this is line three\n"
printf "%b" "$text" > filename
別の解決策はprintf
とsed
を混在させることによって達成されます。
if something
then
printf '%s' '
this is line one
this is line two
this is line three
' | sed '1d;$d;s/^ //g'
fi
インデントレベルをコードにハードコードするので、このようにフォーマットされたコードをリファクタリングするのは簡単ではありません。
ヘルパー関数といくつかの変数置換トリックを使うことは可能です。
unset text
_() { text="${text}${text+
}${*}"; }
# That's an empty line which demonstrates the reasoning behind
# the usage of "+" instead of ":+" in the variable substitution
# above.
_ ""
_ "this is line one"
_ "this is line two"
_ "this is line three"
unset -f _
printf '%s' "$text"
以下は、複数行の文字列を変数に代入するための私の望ましい方法です(私はそれがいいと思う)。
read -r -d '' my_variable << \
_______________________________________________________________________________
String1
String2
String3
...
StringN
_______________________________________________________________________________
どちらの場合も、アンダースコアの数は同じです(ここでは80)。
あなたが以下のようにそれを置けばそれは動作します:
AA='first line
\nsecond line
\nthird line'
echo $AA
output:
first line
second line
third line