read、IFS、whileを一緒に使用すると疑問が生じる

read、IFS、whileを一緒に使用すると疑問が生じる

私は次のことを理解しているので疑問を抱いています:

exec 0</etc/passwd
IFS=:
while read in USUARIO
do
    echo $USUARIO
done

出力はシステムのすべてのユーザーを含むリストであるはずですが、最初の行が必要なのに、代わりに x で埋められた 2 番目の行が取得されます。なぜでしょうか?

また、このスクリプトでは、引数として数値を渡すと、入力した値と同等以上のファイルを持つユーザーのリストが表示されます。

#!/bin/bash

if [[ ( $# -eq 1) && ( $1==[0-9][0-9]* )]]
then
    echo "User with $1 files or more "
    cut -d':' -f1 /etc/passwd | while IFS= read -r USUARIO
    do
        if [[ $( find / -user $USUARIO -print | wc -l ) -ge $1 ]]
        then

            echo $USUARIO
        fi
    done
exit 0
else
    printf "Error: $0 int"
    exit 1
fi

正常に動作しますが、動作しない理由は次のとおりです。

#!/bin/bash

if [[ ( $# -eq 1) && ( $1==[0-9][0-9]* )]]
then
    LIST="Users with more or $1 files: "
    cut -d':' -f1 /etc/passwd | while IFS= read -r USUARIO
    do
        if [[ $( find / -user $USUARIO -print | wc -l ) -ge $1 ]]
        then

            LIST="$LIST $USUARIO"
        fi
    done
echo $LIST
exit 0
else
    printf "Error $0 int"
    exit 1
fi

出力はユーザー名を追加せずに生の文字列になるのはなぜですか?

答え1

forとの構文を混同しているようですwhileforは、リスト内の各要素に対して一連のコマンドを実行します。構文は次のとおりです。 キーワードは、変数名と値のリストとを区切ります。 は、別の一連のコマンドが true である間に一連のコマンドを実行します。構文は次のとおりです。for VARIABLE in VALUES; do COMMANDS; doneinwhilewhile COMMANDS; do COMMANDS; done

コマンドはread1 行を読み取り、それをフィールドに分割します。 の引数は、readフィールド値を設定する変数です。したがって、は最初のフィールドに、 は2 番目のフィールドにread in USUARIO設定されます。または、フィールドが 3 つ以上ある場合 (シナリオの場合)、は残りのすべてのフィールド (内部の区切り文字を含む) に設定されます。 の各呼び出しは1 行を読み取り、各ループ反復は入力の 1 行を処理します。inUSUARIOUSUARIOread

したがって、ユーザー名のみを印刷するには、次のように記述する必要があります。

while IFS=: read USUARIO rest
do
    echo "$USUARIO"
done

2番目の質問に関して(ただし次回は無関係な質問を一緒にしないでください)、問題はパイプライン内の各コマンドがサブシェルで実行されるため、そのうちの1つで設定された変数がパイプラインの外部では表示されないことです。なぜ私の変数は「while read」ループではローカルであるのに、他の似たようなループではローカルではないのでしょうか?

関連情報