파일에서 "while" 지시문의 표준 입력을 어떻게 리디렉션합니까?

파일에서 "while" 지시문의 표준 입력을 어떻게 리디렉션합니까?

저는 쉘 스크립팅을 배우고 있는데 스크립트 작성에 필요한 주요 명령 구조, 특히 while, dodone명령의 개발을 이해하는 데 어려움을 겪고 있습니다.

파일에서 지시문의 표준 입력을 리디렉션할 때 while전체 파일을 읽으면 중지된다는 것을 알고 있습니다(이 경우 파일은 한 줄씩 읽히고 현재 줄은 사용된 변수에 배치됩니다 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

여기 선생님이 전에 $놓쳤는 데 오타인가요? 명령이나 변수의 결과를 얻으려면 이를 사용하여 검색해야 하기 때문입니다.ligwhile$

답변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에 할당되고 두 번째 단어가 두 번째 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: "표준 입력에서 한 줄을 읽고 이를 필드로 나눕니다.". 즉, 전체 줄을 읽고 이를 3개의 다른 부분으로 나누고 각 부분을 사용자가 명명한 3개의 변수에 저장하려고 합니다. 라인에 섹션이 하나만 있는 경우 다른 두 변수는 설정되지 않습니다. $변수의 현재 값을 읽고 싶지 않기 때문에 There를 사용하지 않습니다 .이름변수가 있어야 한다는 것을 알 수 있도록놓다그 가치.

관련 정보