読み取りループ中に読み取りコマンドを使用すると問題が発生します。

読み取りループ中に読み取りコマンドを使用すると問題が発生します。

入力テキストファイルを1行ずつ読み、2つの文字列をテキストファイルの各行の変数として渡すために、while readループ行を設定しようとしています。

    while IFS= read -r line
do
    # Read and pass two path strings as variables.
    read path1 path2
    echo "$path1"
    echo "$path2"
done < "$1"

read path1 path2現在の行の各文字列に変数を割り当てる前に、テキストファイルの次の行を処理するようです。

次の行に移動する前に、各行に文字列を変数として渡すことはできますか?

答え1

readループ本体内の2番目の項目はここでは正しくありません。readwhileループの一部として、実際には最初の呼び出しより1行前です。したがって、あなたの要件に応じて、これらの変数を最初の変数の一部として読みます。read

while read -r path1 path2; do
    echo "$path1"
    echo "$path2"
done < "$1"

ここに示すように、IFS=フィールド区切り文字をリセットすると行全体が選択されるため、両方の変数を読み取るときに設定も正しくありません。 2つの変数を読み取ると、デフォルト値(スペース、タブ、改行などのスペース文字)を使用して、スペースで区切られたリストに各行の値が格納されます。このようにして、行を区切るn個の列を持つことができ、n個の変数を使用して読み取ることができます。

これで、これらの変数で値を使用でき、必要に応じて他のコマンドに渡すことができます。

サンプル入力ファイルでこれがどのように機能するかを見てみましょう。

foo bar
foo1 bar1
foo2 bar2

-xset を使用してデバッグモードで最初のスクリプトを実行します。

$ bash -x script.sh
+ read -r path1 path2
+ echo 1
1
+ echo 2
2
+ read -r path1 path2
+ echo 3
3
+ echo 4
4
+ read -r path1 path2
+ echo abc
abc
+ echo def
def
+ read -r path1 path2

答え2

ラインをそのまま維持したい場合そしてそれから値を抽出するには、次を使用できます。ここにある文字列:

while IFS= read -r line; do
    read -r path1 path1 <<< "$line"
    echo "$line"
    echo "$path1:$path2"
done < file

実際、すべてのシェルがhere-stringをサポートしているわけではありません。ただし、このドキュメントはすべてのPOSIXタイプシェルでサポートされています。

while IFS= read -r line; do
    read -r path1 path1 << _LINE_
$line
_LINE_
    echo "$line"
    echo "$path1:$path2"
done < file

答え3

ファイルをforループにリダイレクトすると、ループ全体で標準入力のすべての読み取りが同じファイルから読み取られます。つまり、readループ内の2つのコマンドは、最初の引数としてスクリプトに渡したファイルから代替行を読み取ります。

path1データをどこから取得したいのか少し不明ですpath2。ファイルからそれを読むには、ループヘッダーで実行します。

while read -r path1 path2; do
    printf 'path1 = "%s"\n' "$path1"
    printf 'path2 = "%s"\n' "$path2"
done <"somefile"

この回答の残りの部分では、ファイルから何かを読み、次にループの端末で何かを読み取ろうとします。

readループ本体を端末から読み取るには:

exec 3<"somefile"

while IFS= read -r words <&3; do
   read -r word1 word2 junk
   printf 'Got words = "%s"\n' "$words"
   printf 'Got word1 = "%s"\n' "$word1"
   printf 'Got word2 = "%s"\n' "$word2"
done

これにより、最初の入力はreadファイルから出力されsomefile、2番目の標準入力ストリームはread端末(またはスクリプトの標準入力ストリームが出てくる場所)から読み取られます。

関連情報