책에서 bash/ksh를 배울 때. 결과를 알고 싶은 운동을 발견했습니다.
동작(디버깅)을 이해하기 위해 bash -x를 사용하여 이 스크립트를 실행할 때 줄 변수가 숫자 + 파일 이름이라는 것을 알았습니다. 이는 wc -c [파일]의 결과이기 때문입니다. 그러나 for 루프가 res 변수를 설정하면 어떻게든 파일 이름이 제거되고 res=23
(wc -c의 숫자 결과)만 표시됩니다. 이러한 일이 발생하는 것은 볼 수 있지만 그 이유를 잘 이해할 수 없습니까? 나는 for 루프 구조를 이해한다고 생각합니다. for i in xxx의 기능은 무엇입니까.. 이 구조의 중단을 100% 이해하지는 못하지만 중첩 루프를 중단하는 것임을 알고 있습니다.
연습 스크립트는 다음과 같습니다.
if [ ! $# -eq 2 ] ;then
echo
echo "usage: $0 <location> <FileName>"
echo
exit 1
fi
TMPFILE=/tmp/count
line=$(find "$1" -name "$2" -type f -print | tee $TMPFILE | wc -l)
aant=$line
nr=0
som=0
while [ $nr -lt "$aant" ] ; do
nr=$(( nr +1 ))
bestand=$(head -$nr $TMPFILE | tail -1)
echo -n "$bestand"
line=$(wc -c "$bestand")
for woord in $line ; do
res=$woord
break
done
echo " $res"
som=$(( som + res ))
done
if [ "$aant" -eq 0 ] ; then
echo "No files found"
else
echo
echo "In totaal $aant files take $som bytes of space"
fi
rm $TMPFILE
exit 0
답변1
for word in $line
, 변수의 내용은 line
다음 과 같습니다단어로 나누기그런 다음 파일 이름 전역 변수를 확장합니다(참조:이것들 질문). 그런 다음 루프는 각 결과 값(또는 "단어")에 대해 한 번씩 실행됩니다. 그러나 이 경우 이 break
명령문이 루프 실행을 중지하므로 루프에는 최대 한 번의 반복이 있습니다. 따라서 res
루프의 첫 번째 반복에서 set 값은 그대로 유지되며, 이는 공백으로 구분된 첫 번째 단어를 선택하는 것과 동일한 효과를 갖습니다 line
.
이를 작성하는 더 좋은 방법이 있을 것입니다. 예를 들어 쉘 확장을 사용하여 파일 이름을 제거할 수 있습니다. 그러면 다음이 출력됩니다 23
.
line='23 somefilename'
res="${line%% *}"
echo "$res"
또는 파일 이름을 에 전달하는 대신 wc
파일을 stdin으로 리디렉션하여 파일 이름을 출력 하지 않습니다 .wc
wc
$ wc -c foo.txt
8 foo.txt
$ wc -c < foo.txt
8
답변2
귀하의 질문을 올바르게 이해하면 여기서 마법이 일어납니다.
for woord in $line ; do
res=$woord
break
done
이것이 어떻게 작동하는지 이해하는 데 도움이 되도록 다음을 생각하는 것이 도움이 될 수 있습니다.
for N in 1 2 3 4 5; do
echo $N
done
echo "N is $N"
다음으로 " break
" 문을 추가하고 다음을 고려하세요.
for N in 1 2 3 4 5; do
echo $N
break
done
echo "N is $N"
루프 break
에 명령문을 추가하는 것이 무엇인지 설명할 수 있습니까 ?for
내가 원래 인용한 네 줄의 코드는 단 세 줄로 줄어들 수 있을 것 같습니다.
for res in $line ; do
break
done
이는 본질적으로 "서투른" 표현 방식입니다.
res="$(awk '{print $1}' <<< "$line")"
답변3
매뉴얼 페이지를 확인하십시오 wc -c
.
bytecount filename
공백 으로 구분된 목록을 출력합니다 $line
.
루프 for $woord in $line
는 (첫 번째 공백까지) 에서 첫 번째 변수를 읽습니다 $list
. 즉, bytecount
에 저장합니다 $res
. 그런 다음 다음 항목을 계속 읽는 대신 명령을 $list
실행 break
하고 루프를 종료합니다.
bytecount
@ikkachu가 말했듯 이 반복하는 것보다 더 쉽게 얻을 수 있는 방법이 있습니다 .