この複数行の文字列があります(引用符が含まれています):
abc'asdf"
$(dont-execute-this)
foo"bar"''
Bashでヒアドキュメントを使用して変数に割り当てるにはどうすればよいですか?
改行を保持する必要があります。
文字列内の文字をエスケープしたくないので、面倒です...
これにより、無駄な使用を避け、cat
引用符の不一致をより適切に処理できます。
$ read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
エコーするときに変数を引用しないと、改行が失われます。それを引用すると、それらが保持されます。
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
ソース コードを読みやすくするためにインデントを使用する場合は、小なり記号の後にダッシュを使用します。インデントは、タブのみ (スペースなし) を使用して行う必要があります。
$ read -r -d '' VAR <<-'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
代わりに、結果の変数の内容にタブを保持したい場合は、からタブを削除する必要がありますIFS
。ヒア ドキュメント ( ) の終端マーカーはEOF
インデントしてはなりません。
$ IFS='' read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''
Ctrl-を押すと、コマンドラインでタブを挿入できますV Tab。エディターを使用している場合、エディターによっては、それも機能するか、タブをスペースに自動的に変換する機能をオフにする必要がある場合があります。
$() を使用して、次のcat
ように出力を変数に割り当てます。
VAR=$(cat <<'END_HEREDOC'
abc'asdf"
$(dont-execute-this)
foo"bar"''
END_HEREDOC
)
# this will echo variable with new lines intact
echo "$VAR"
# this will echo variable without new lines (changed to space character)
echo $VAR
END_HEREDOC の開始を必ず一重引用符で区切ります。
終了ヒアドキュメント区切り文字END_HEREDOC
は行に単独である必要があることに注意してください (したがって、終了括弧は次の行にあります)。
@ephemient
答えてくれてありがとう。
これは Dennis メソッドのバリエーションで、スクリプトではよりエレガントに見えます。
関数定義:
define(){ IFS='\n' read -r -d '' ${1} || true; }
利用方法:
define VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
echo "$VAR"
楽しい
ps は、をサポートしないシェル用の「読み取りループ」read -d
バージョンを作成しました。set -eu
とunpaired backticksで動作するはずですが、十分にテストされていません:
define(){ o=; while IFS="\n" read -r a; do o="$o$a"'
'; done; eval "$1=\$o"; }
VAR=<<END
abc
END
標準入力を気にしないもの、つまり割り当てにリダイレクトしているため、機能しません
export A=`cat <<END
sdfsdf
sdfsdf
sdfsfds
END
` ; echo $A
動作しますが、これを使用できなくなる可能性があるバックティックがあります。また、バッククォートの使用は絶対に避けてください。コマンド置換表記法を使用することをお勧めします$(..)
。
export A=$(cat <<END
sdfsdf
sdfsdf
sdfsfds
END
) ; echo $A
改行を保持する解決策はまだありません。
これは正しくありません。おそらく、echo の動作に惑わされているだけです。
echo $VAR # strips newlines
echo "$VAR" # preserves newlines
配列は変数なので、その場合は mapfile が機能します
mapfile y <<'z'
abc'asdf"
$(dont-execute-this)
foo"bar"''
z
次に、このように印刷できます
printf %s "${y[@]}"
VAR="$(cat <<'VAREOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
VAREOF
)"
echo "$(cat <<'SQLEOF'
xxx''xxx'xxx'xx 123123 123123
abc'asdf"
$(dont-execute-this)
foo"bar"''
SQLEOF
)"
dimo414's answer のおかげで、これは彼の優れたソリューションがどのように機能するかを示し、テキストに引用符と変数を簡単に含めることができることを示しています。
$ ./test.sh
The text from the example function is:
Welcome dev: Would you "like" to know how many 'files' there are in /tmp?
There are " 38" files in /tmp, according to the "wc" command
#!/bin/bash
function text1()
{
COUNT=$(\ls /tmp | wc -l)
cat <<EOF
$1 Would you "like" to know how many 'files' there are in /tmp?
There are "$COUNT" files in /tmp, according to the "wc" command
EOF
}
function main()
{
OUT=$(text1 "Welcome dev:")
echo "The text from the example function is: $OUT"
}
main
NULL を含む文字列を読み取らなければならないことに気付いたので、投げたものをすべて読み取るソリューションを次に示します。ただし、実際に NULL を処理している場合は、16 進レベルで処理する必要があります。
$ 猫 > read.dd.sh
read.dd() {
buf=
while read; do
buf+=$REPLY
done < <( dd bs=1 2>/dev/null | xxd -p )
printf -v REPLY '%b' $( sed 's/../ \\\x&/g' <<< $buf )
}
証拠:
$ . read.dd.sh
$ read.dd < read.dd.sh
$ echo -n "$REPLY" > read.dd.sh.copy
$ diff read.dd.sh read.dd.sh.copy || echo "File are different"
$
HEREDOC の例 (^J、^M、^I を使用):
$ read.dd <<'HEREDOC'
> (TAB)
> (SPACES)
(^J)^M(^M)
> DONE
>
> HEREDOC
$ declare -p REPLY
declare -- REPLY=" (TAB)
(SPACES)
(^M)
DONE
"
$ declare -p REPLY | xxd
0000000: 6465 636c 6172 6520 2d2d 2052 4550 4c59 declare -- REPLY
0000010: 3d22 0928 5441 4229 0a20 2020 2020 2028 =".(TAB). (
0000020: 5350 4143 4553 290a 285e 4a29 0d28 5e4d SPACES).(^J).(^M
0000030: 290a 444f 4e45 0a0a 220a ).DONE
$TEST="ok"
read MYTEXT <<EOT
this bash trick
should preserve
newlines $TEST
long live perl
EOT
echo -e $MYTEXT