私はシェルスクリプトを学んでいますが、スクリプトの作成に必要な主要なコマンド構造、特に、およびwhile
コマンドdo
のdone
開発を理解するのが困難です。
ファイルからディレクティブの標準入力をリダイレクトするときにファイル全体を読み込むとwhile
停止することがわかります(この場合、ファイルは1行ずつ読み取られ、現在の行は使用されている変数に配置されますread
)。
while read lig fich
do
...
done < fich
これは現在行全体があることを意味しますかfich
?
例:このスクリプトはユーザー名と文字列を引数として使用し、名前に文字列を含むユーザー名が所有するファイルを検索します。
#usage nblign nom-utilisateur chaine
find . -user $1 | grep $2 >temp
while read lig temp
do
echo $lig "nombre de ligne" `wc -l < $lig`$
done < temp
rm temp
ここの先生が前に$
逃したのに太田ですか?コマンドまたは変数の結果を取得するには、それを使用して検索する必要があるためです。lig
while
$
答え1
いくつかの誤解があります。最初にwhile read ... do
使用したい形式は次のとおりです。
while read var; do ...; done < file
まさか
while read var file; do ...; done < file
デフォルトでは、各行while read var; do ...; done < file
はfile
として読み書きされますvar
。read
との間のすべての値はdo
変数と見なされます。複数の変数を指定した場合、行は空白(デフォルトでは変数値と空白)に分割され、指定された変数$IFS
に保存されます\t
。\n
説明したようにhelp read
:
標準入力または-uオプションが指定されている場合は、ファイル記述子FDから行を読み取ります。単語分割と同様に、行は最初の単語が最初のNAMEに割り当てられ、2番目の単語が2番目のNAMEに割り当てられるなどのフィールドに分割され、残りのすべての単語は最後のNAMEに割り当てられます。
たとえば、次のようになります。
$ echo "foo bar baz zab" | while read v1 rest; do echo "v1:$v1, rest:$rest"; done
v1:foo, rest:bar baz zab
$ echo "foo bar baz zab" | while read v1 v2 rest; do echo "v1:$v1, v2:$v2, rest:$rest"; done
v1:foo, v2:bar, rest:baz zab
$ echo "foo bar baz zab" | while read v1 v2 v3 rest; do echo "v1:$v1, v2:$v2, v3:$v3, rest:$rest"; done
v1:foo, v2:bar, v3:baz, rest:zab
上記のように、入力行はユーザーが指定した数の変数に分割されます。入力に変数名が「単語」未満の場合、最後の変数は行の残りの部分を占めます。これはファイルから読み取るときとまったく同じです。
次に、var="foo"
と を使って変数を設定します。読む使用$var
。いいえ、先生の言葉が正しいです。$
変数が定義される時間を望まないことです。だからwhile read var
それは正しいwhile read $var
と正しいです。
したがって、同じロジックを使用するスクリプトの作業バージョンは次のようになります。
find . -user $1 | grep $2 >temp
while read lig
do
echo $lig "nombre de ligne" `wc -l < $lig`
done < temp
rm temp
行末からおよびをtemp
削除しました。read
それをなぜそこに置いたのか分からないですね。$
echo
変数を含むより良いバージョンのスクリプト正しい引用find
、解析を試みるのではなく、不要な一時ファイルなしで関連ファイルの検索を使用することは次のとおりです。
find . -user "$1" -name "*$2*" |
## No need for a temp file, just pipe the output directly
## to the while loop
while read lig
do
echo "$lig nombre de ligne: $(wc -l < "$lig")"
done
最後に、上記の方法とは異なり、スペースやその他の奇妙な文字を含む任意のファイル名を処理することができる非常に強力な方法です。
find . -user "$1" -name "*$2*" -print0 |
## No need for a temp file, just pipe the output directly
## to the while loop
while IFS= read -r -d '' lig
do
echo "$lig nombre de ligne: $(wc -l < "$lig")"
done
答え2
送信者help read
:「標準入力から1行を読み、それをフィールドに分割します。」つまり、行全体を読み、3つの異なる部分に分割し、各部分をユーザーが名前付き3つの変数に保存しようとします。行にセクションが1つしかない場合、他の2つの変数は設定されません。$
変数の現在の値を読みたくないため、Thereを使用しません。名前変数がなければならないことがわかるように置くその価値。