루프 반복 횟수를 계산하기 위해 정수를 사용하려고 하는데 루프가 완료된 후 변수가 비어 있습니다. 단서를 찾았지만 운이 없습니다.
나는 이 코드를 가지고 있습니다 :
#!/bin/bash
declare -i count
echo entering loop
while read var
do
(( count++ ))
echo $count
done
echo exited loop
echo count is $count
대화형으로 실행하면 "c"를 입력한 후 Ctrl+D를 누르면 다음과 같은 결과가 나타납니다.
$ ./example
entering loop
a
1
b
2
c
3
exited loop
count is 3
하지만 루프에 입력을 공급하면 다음과 같습니다.
#!/bin/bash
declare -i count
echo entering loop
ls -la | while read var
do
(( count++ ))
# do something interesting here
echo $count
done
echo exited loop
echo count is $count
...이 결과는 다음과 같습니다.
$ ./example
entering loop
1
2
3
4
5
exited loop
count is
$
루프를 종료한 후 "count is 5"가 나타나지 않는 이유는 무엇입니까?
답변1
while 루프에 값을 파이프하면 파이프의 명령이 서브셸에서 실행되고 while 루프가 끝나면 카운터 변수의 값이 손실됩니다.
다음을 사용하여 이 문제를 해결할 수 있습니다.프로세스 교체파이프 대신:
#!/bin/bash
declare -i count
while read var
do
((count++))
echo "$count"
done < <(ls -la)
echo "count is $count"
또는 현재 셸 컨텍스트에서 파이프라인의 마지막 명령을 실행하는 lastpipe
기능을 활성화할 수 있습니다.bash
https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
lastpipe
설정되어 있고 작업 제어가 활성화되지 않은 경우 셸은 백그라운드에서 실행되지 않는 현재 셸 환경에서 파이프라인의 마지막 명령을 실행합니다.
#!/bin/bash
declare -i count
shopt -s lastpipe # enable lastpipe
ls -la | while read var
do
((count++))
echo "$count"
done
shopt -u lastpipe # disable lastpipe
echo "count is $count"
관련된:
답변2
BASH 매뉴얼의 섹션 3.2.2를 참조하십시오.https://www.gnu.org/software/bash/manual/bash.html
각 파이프라인은 별도의 하위 셸에서 실행되므로 파이프라인 명령의 count 변수 업데이트는 범위를 벗어납니다.
그러나 shopt -s lastpipe
스크립트 시작 부분의 기본 범위를 사용하여 최종 파이프라인 실행을 설정할 수 있습니다. 이렇게 하면 카운터 변수가 스크립트의 기본 셸과 동일한 범위로 업데이트되어 최종 카운터 값이 복원될 수 있습니다.