私は bash 言語を勉強していて、試験トラックはこれを言っています:
一度に1つの入力を(標準入力から)読み取る必要があります(各エントリは文字列であり、改行で終了します)。
私の質問は2つです。
Bashの標準入力から1行ずつ読み取るにはどうすればよいですか?今までは"read string"
しかし、一度に1行ずつ読み取るとは思いません。
これが愚かな質問であるかどうかはわかりませんが、スクリプトを作成したら、スクリプトにさらに多くの行を入力として指定できます(もちろん、標準入力から読み取ります)。たとえば stdin から2行(hello
およびworld
)を挿入します。これらの2行をbashスクリプトに与えるにはどうすればよいですか?
- Bashの標準入力から1行ずつ読み取るにはどうすればよいですか?今までは「文字列を読む」を使っていましたが、一度に行を読むとは思いませんでした。
read
のプロトタイプは次のとおりです。
read [options] name[s ...]
read
はline
の入力をname name1 name2 ...
に読み取り、内部フィールドセパレーターの内容に基づいて行を分割します(IFS
)。 IFS
のデフォルトは' \t\n'
です(つまり、space
tab
newline
)。 read
に1つの変数のみを指定すると、行全体がその変数に読み込まれます(-d
オプションを使用して新しい区切り文字をread
に設定していない場合)。複数の変数を指定した場合(read -r name name1
など)、IFS
の現在の値に基づいて単語分割が行われます。文字列hello world
を次のように指定した場合の意味:
read -r name
name="hello world"
。一方、同じ文字列を次のように指定すると、
read -r name name1
name="hello"
、name1="world"
。行に余分な単語があり、変数が2つしかない場合はどうなりますか?文字列が"hello big wide world"
になったとしましょう。
read -r name name1
name="hello"
、name1="big wide world"
。 string
の単語は順番に変数に割り当てられ、文字列内の各単語を保持するのに十分な変数がない場合、最後の変数には、以前に割り当てられていない文字列の残りのすべての単語が含まれます。
IFS
を変更して、Word分割の発生方法を変更します。例として、anubhavaが提供する答えを詳しく見てみましょう。単語を分割する任意の文字を自由に指定できます。 (たとえば、csv
ファイルを解析してIFS=$',\n'
を設定し、単語をスペースではなく','
で分割するのに役立ちます)
行全体を確実に変数に読み込むには、read
に1つの変数のみを提供し、IFS='$\n'
を設定して、Word分割がnewline
でのみ行われるようにします。 (注:while
ループの一部として変更を提供すると、IFS
の変更がそのループのスコープに制限されます。 例えば:
while IFS='$\n' read -r line; do
# do whatever with line
done
stdin
の各行がline
に確実に読み込まれ、ループの外側で通常の単語分割が維持されます。ループ内では、anubhavaが答えに示すように、各行を配列に追加できます。 (すべての空白を保持するためにIFS=
が使用されます)
あなたはこのようなことをすることができます:
# array to hold all lines read
lines=()
# read all lines in lines array
while IFS= read -r line; do
lines+=( "$line" )
done < file
# read 3 more lines from stdin
for ((i=0; i<3; i++)); do
read -rp "Enter a line: " line
lines+=( "$line" )
done