私は次のことを理解しているので疑問を抱いています:
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
との構文を混同しているようですwhile
。for
は、リスト内の各要素に対して一連のコマンドを実行します。構文は次のとおりです。 キーワードは、変数名と値のリストとを区切ります。 は、別の一連のコマンドが true である間に一連のコマンドを実行します。構文は次のとおりです。for VARIABLE in VALUES; do COMMANDS; done
in
while
while COMMANDS; do COMMANDS; done
コマンドはread
1 行を読み取り、それをフィールドに分割します。 の引数は、read
フィールド値を設定する変数です。したがって、は最初のフィールドに、 は2 番目のフィールドにread in USUARIO
設定されます。または、フィールドが 3 つ以上ある場合 (シナリオの場合)、は残りのすべてのフィールド (内部の区切り文字を含む) に設定されます。 の各呼び出しは1 行を読み取り、各ループ反復は入力の 1 行を処理します。in
USUARIO
USUARIO
read
したがって、ユーザー名のみを印刷するには、次のように記述する必要があります。
while IFS=: read USUARIO rest
do
echo "$USUARIO"
done
2番目の質問に関して(ただし次回は無関係な質問を一緒にしないでください)、問題はパイプライン内の各コマンドがサブシェルで実行されるため、そのうちの1つで設定された変数がパイプラインの外部では表示されないことです。なぜ私の変数は「while read」ループではローカルであるのに、他の似たようなループではローカルではないのでしょうか?