私は以下のパターンを使用してbashスクリプトの端末に複数行のメッセージを印刷しました。
read -d '' message <<- EOF
this is a
mulitline
message
EOF
echo "$message"
これは働いていました。数日前まではモード動作が中断されました。動作を停止するということは、bashがスクリプトでこれらの区切り文字表現を見つけたときに何もしないようで、出力がないことを意味します。
過去数日間に私が考えることができる唯一の変更は、スクリプトが実行される環境が「フル」インストールではなく、Ubuntu 14.04ライブUSBであるということです。その後、スクリプトステートメントの前に
heredocを移動すると、再び機能し始めることがわかりました。set -o errexit
つまり、これは機能しません
#!/bin/bash
set -o errexit
read -d '' message <<- EOF
this is a
mulitline
message
EOF
echo "$message"
結果:(何も)
しかしこれは実際に働く
#!/bin/bash
read -d '' message <<- EOF
this is a
mulitline
message
EOF
echo "$message"
結果
$ sudo ./script.sh
this is a
mulitline
message
- バッシュ --バージョン-
GNU bash, version 4.3.11(1)-release (i686-pc-linux-gnu)
答え1
read
区切り文字が見つからない場合は、ゼロ以外の終了ステータスが返されます。区切り文字を空の文字列に設定した後、通常はテキストファイルに見つからないNULバイトを区切り文字として使用します。
答え2
EOF(ファイルの終わり)表示に達すると、読み取りコマンドの終了コードは1です。この特別な場合は、-d
区切り文字が空のときに常に発生します''
。ここで、ソースストリームは\ 0を含めることができない区切り文書です。
$ read -d '' message <<-_ThisMessageEnds_
> this is a
> multi line
> message
> _ThisMessageEnds_
$ exitval=$?
$ echo "The exit val was $exitval"
The exit val was 1.
終了値はエラー(0ではありません)で、AND / OR構文を使用してスクリプトの終了を防ぐことができます。
read -d '' message <<-_ThisMessageEnds_ || echo "$message"
this is a
multi line
message
_ThisMessageEnds_
これによりメッセージがコンソールに送信されますが、コンソールのシャットダウンは防ぎますerrexit
。
しかし今後は縮小する予定なので、ただ使ってみてはいかがでしょうか?
cat <<-_ThisMessageEnds_
this is a
mulitline
message
_ThisMessageEnds_
読み取りコマンドがより速く実行され、変数が必要なく、終了コードにエラーがなく、維持するコードが少なくなります。
答え3
read -d '' message
最初にエスケープされていない最初のNUL文字(1つを追加しなかったため-r
)または入力の最後まで標準入力を読み取り、$IFS
バックスラッシュ文字で処理されたデータを区切り文字$message
なしで保存します。
入力にエスケープされていない区切り文字がない場合、終了ステータスはread
ゼロではありません。完全終了レコードを読み取ると、0(成功)のみが返されます。
NULで区切られたレコード(出力など)を処理するのに最も便利です(後で構文がfind -print0
必要な場合でも)。IFS= read -rd '' record
read
正常な戻りを得るには、この文書にNUL区切り文字を含める必要があります。ただしbash
、このドキュメントからNUL文字を削除することは不可能です(yash
ここにドキュメントにNULが含まれているときに無限ループに入るように見える最初のNULまたはksh93以降のすべてのアイテムを削除するよりも少なくとも優れています)。
zsh
ドキュメントに NUL を含めたり、変数に保存したり、組み込み関数/関数に NUL 文字を引数として渡したりできる唯一のシェルです。では、zsh
次のことができます。
NUL=$'\0'
IFS= read -d $NUL -r var << EOF
1
2
3$NUL
EOF
( . のような NUL 区切り文字としてもzsh
理解されますが、NUL バイトはコマンドラインでサポートされていないため、 like in に空の引数を渡します。)read -d ''
bash
read -d $'\0'
bash
read
read -d ''
bash
(次に改行があることに注意してください$NUL
)
bash
さまざまな文字を使用できます。
ONE=$'\1'
IFS= read -d "$ONE" -r var << EOF
1
2
3$ONE
EOF
しかし、次のようにすることもできます。
var=$(cat <<EOF
message
here
EOF
)
それでもNUL文字は使用できません。ただし、これは標準コードなので、zsh / bash固有のコードに頼る必要はありませんread -d
。また、すべての末尾の改行を削除するため、組み込みksh93
機能が有効になっていないcat
場合は追加のプロセスとコマンドが生成されます。
答え4
使用set -o errexit
してスクリプトが中断されると、何かが間違っていることを意味します。
ここはread
, 入力内容を正しく読み取れません。
でbash
使用するread -d ''
ときread
組み込み\0
ヌル文字は行終端として使用されます。したがって、\0
入力に何もない場合は、read
すべての入力が変数として読み取られ、message
ゼロ以外の終了ステータスが返され、エラーを示します。
$ while read -d '' line; do echo "$line"; done < <(printf '1')
次の場合は何も印刷しません。
$ while read -d '' line; do echo "$line"; done < <(printf '1\0')
1
あなたのための1
。
read
また、EOFに達するとゼロ以外の状態を返しますが、これはループread
と一緒に使用するとwhile
読み取る入力がなくなり、while
ループが終了する可能性があることを示すために使用されます。これはあなたの質問とは関係ありません。