2

Bashでヒアドキュメントから複数行の変数を読み取る完璧な方法は何ですか?

私のやり方には、次のように戻るという副作用があることを見て1ください$?...


バッシュコード:

#!/bin/bash

printf "Unsetting...\n"
unset variable
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"

printf "\n"

printf "Setting to 'foo'...\n"
variable='foo'
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"

printf "\n"

printf "Setting to 'bar' by reading stdin from process substitution...\n"
read variable < <(echo 'bar')
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"

printf "\n"

printf "Setting to 'baz' by reading stdin from Here String...\n"
here_string='baz'
read variable <<< "${here_string}"
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"

printf "\n"

printf "Setting to 'quux' by reading stdin from Here Document...\n"
read variable <<- 'EOF'
quux
EOF
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"

printf "\n"

printf "Setting to 'thud <newline> thud' by reading stdin from Here Document...\n"
read -d '' variable <<- 'EOF'
thud
thud
EOF
printf "Exit status: %s.\n" "$?" # ONE?!one!!oneone? :)
printf "Variable: %s.\n" "${variable}"

出力

Unsetting...
Exit status: 0.
Variable: .

Setting to 'foo'...
Exit status: 0.
Variable: foo.

Setting to 'bar' by reading stdin from process substitution...
Exit status: 0.
Variable: bar.

Setting to 'baz' by reading stdin from Here String...
Exit status: 0.
Variable: baz.

Setting to 'quux' by reading stdin from Here Document...
Exit status: 0.
Variable: quux.

Setting to 'thud <newline> thud' by reading stdin from Here
Document...
Exit status: 1.
Variable: thud
thud.
4

4 に答える 4

4

read最後に読み取った結果を割り当てると同時に、EOF に達すると 1 を返します。これが、改行で終わらないファイルが問題になる理由です。単純なループでreadは最終行のループ本体が実行されないためです。

read -d ''入力に ​​NUL バイトを入れずに使用すると、これはファイルの最後の行を読み取るのと同じです。read問題は、この場合、なぜ 0 を返したいのかということです。正常に動作しています。また、ヒアドキュメント (およびヒアストリングス) は常に末尾に改行を自動的に追加することに注意してください。

やや関連:

于 2013-03-14T23:33:43.173 に答える
4

read問題は、ASCII NUL 文字が表示される前にファイルの終わりが表示されることだと思います。ただし、それが true の場合、以下は 0 で終了する必要があります。

read -d '' variable <<< $'thud\nthud\x00'

しかし、そうではありません。

実際の修正の代わりに、次のハックを提供できます。コマンドが実際に 0 を返さないようにするため、ログイン スクリプトを壊すことはありません。

read -d '' variable <<-'EOF' || true
thud
thud
EOF

readそれでも 1 で終了しますが、これはシェルにtrueコマンドを実行させるだけであり、0 で終了することが保証されています。

于 2013-03-14T22:42:11.610 に答える
3

mapfileまたはそのエイリアスを使用して、ヒアドキュメントを配列に読み込むことができますreadarray

mapfile var <<-'EOF'
thud
thud
EOF

その結果

var=([0]="thud
" [1]="thud
")

そして、配列要素を連結するだけです。

variable=${var[0]}
variable+=${var[1]}
...

可変長の配列の場合、ループでこれを行うか、printf組み込み関数を使用できます (eush77 に感謝):

printf -v variable "%s" "${var[@]}"

どちらのオプションも結果として

variable=$'thud\nthud\n'

終了ステータスが 1 だった理由は、Sorpigal によって既に示されています。

于 2013-03-14T23:12:31.467 に答える
3

read区切り文字に到達せずにファイルの終わりに到達すると、0 以外の値を返します。どうやら \0 は区切り文字であるかどうかにかかわらず EOF として扱われます。これを防ぐための 1 つのハックは、ありそうもない区切り文字を選択し、文字列の最後にそれを埋め込むことです。例:

read -r -d $'\3' variable <<<"thud\nthud\n"$'\3' ; echo $?

とはいえ、ヒアドキュメントでこれを行うのはより困難です。

于 2013-03-14T22:55:12.153 に答える