![while 루프 후에 배열이 비어 있는 이유는 무엇입니까? [복사]](https://linux55.com/image/86470/while%20%EB%A3%A8%ED%94%84%20%ED%9B%84%EC%97%90%20%EB%B0%B0%EC%97%B4%EC%9D%B4%20%EB%B9%84%EC%96%B4%20%EC%9E%88%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F%20%5B%EB%B3%B5%EC%82%AC%5D.png)
다음과 같은 방법으로 bash-4.2에서 배열을 초기화하려고 합니다.
ring=()
ls -las | tail -n +4 | while read line
> do
> ring+=("$line")
> echo ${ring[-1]}
> done
3924 -rw-r--r-- 1 username group 4015716 Mar 23 15:14 script.jar
4 -rw-r--r-- 1 username group 9 Feb 29 12:40 rec.lst
5541 -rw-r--r-- 1 username group 5674226917 Mar 28 15:25 debug.out
8 -rw-r--r-- 1 username group 6135 Mar 25 12:16 script.class
8 -rw-r--r-- 1 username group 6377 Mar 25 11:57 script.java
8 -rwxr-xr-x 1 username group 4930 Mar 8 15:21 script-0.0.0.sh
8 -rwxr-xr-x 1 username group 6361 Mar 28 15:27 script-0.0.1.sh
echo ${ring[0]}
echo "${ring[0]}"
echo "${ring[@]}"
무엇이 잘못되었으며 루프가 끝난 후 빈 배열이 나타나는 이유는 무엇입니까?
답변1
문제는 파이프( command1 | command2 | command3 ...
)에서 명령이 하위 쉘에서 실행된다는 것입니다. 변수는 서브쉘 간이나 서브쉘과 메인 쉘 간에 공유되지 않습니다. while 루프 내부의 루프는 ring
기본 셸의 루프와 다릅니다.ring
이 문제를 극복하는 한 가지 방법은 프로세스 대체를 사용하는 것입니다.
while read line; do ring+=("$line"); echo ${ring[-1]}; done < <(ls -las|tail -n +4)
문법 <(command)
이라고 합니다프로세스 교체명령의 출력을 명명된 파이프로 리디렉션합니다. 그런 다음 <
마치 파일인 것처럼 익숙한 파일로 리디렉션됩니다 . 를 사용하면 <
서브쉘이 없으므로 ring
이 변수가 설정됩니다.
파일의 줄에서 배열을 채우는 쉘이 내장되어 있습니다.
mapfile -t ring < <(ls -las | tail -n +4)
답변2
이것은 잘 작동합니다:
ring=()
while read line
do
ring+=("$line")
echo ${ring[-1]}
done < <(ls -las | tail -n +4)
답변3
그 이유는 while 루프가 파이프로 연결되어 있기 때문에 서브셸에서 실행되기 때문입니다. 서브쉘은 상위 쉘 환경의 사본을 사용하며 서브쉘이 종료될 때 이를 다시 전달하지 않습니다.
Bash의 경우 명령 그룹화 해결 방법을 사용할 수 있습니다. 추가된 중괄호에 유의하세요.
ls -las | tail -n +4 | { while read line; do ring+=("$line"); echo ${ring[-1]}; done; echo ${ring[0]}; }