어떻게 작동하나요? for 루프는 변수 결과를 제거합니다.

어떻게 작동하나요? for 루프는 변수 결과를 제거합니다.

책에서 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으로 리디렉션하여 파일 이름을 출력 하지 않습니다 .wcwc

$ 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가 말했듯 이 반복하는 것보다 더 쉽게 얻을 수 있는 방법이 있습니다 .

관련 정보