Bash에서 중첩 for 루프를 사용하는 방법을 모르겠습니다. 다음 코드를 중첩된 for 루프로 어떻게 바꿀 수 있나요?
~/
❯ cat sequential.sh
a=(1 2)
b=(3 4)
c=(5 6)
for e in "${a[@]}"
do
echo $e
done
for e in "${b[@]}"
do
echo $e
done
for e in "${c[@]}"
do
echo $e
done
✦ ~/
❯ bash sequential.sh
1
2
3
4
5
6
답변1
루프와 관련된 "중첩"이란 일반적으로 하나의 루프를 다른 루프 안에 넣어서 내부 루프의 각 반복 집합이 외부 루프의 각 반복에 대해 실행되도록 하는 것을 의미합니다.
for letter in a b c; do
for digit in 1 2 3; do
printf 'Letter = %s\tDigit = %s\n' "$letter" "$digit"
done
done
...산출
Letter = a Digit = 1
Letter = a Digit = 2
Letter = a Digit = 3
Letter = b Digit = 1
Letter = b Digit = 2
Letter = b Digit = 3
Letter = c Digit = 1
Letter = c Digit = 2
Letter = c Digit = 3
그러나 귀하의 질문에 따르면 여전히 동일한 출력을 원한다고 가정하면 중첩을 수행하고 싶지 않은 것 같습니다. 대신에 당신이 원하는결합하다세 개의 개별 루프를 하나의 루프로 결합합니다.
이는 루프 헤더에 배열 확장을 하나씩 추가하여 반복할 더 큰 문자열 세트를 생성함으로써 수행됩니다.
a=(1 2)
b=(3 4)
c=(5 6)
for item in "${a[@]}" "${b[@]}" "${c[@]}"
do
printf 'item is "%s"\n' "$item"
done
이는 세 개의 작은 배열에서 별도의 요소 배열을 만들고 더 큰 배열을 반복하는 것과 동일한 효과를 갖습니다.
a=(1 2)
b=(3 4)
c=(5 6)
combined=( "${a[@]}" "${b[@]}" "${c[@]}" )
# the above has the effect of setting the combined array as
# combined=( 1 2 3 4 5 6 )
for item in "${combined[@]}"; do
printf 'item is "%s"\n' "$item"
done
또는 더 짧게 위치 인수 목록을 사용합니다.
a=(1 2)
b=(3 4)
c=(5 6)
set -- "${a[@]}" "${b[@]}" "${c[@]}"
for item do
printf 'item is "%s"\n' "$item"
done
이는 중첩이 아니라 배열 요소의 세 가지 개별 세트를 더 큰 세트로 결합하는 것입니다.
printf
우리가 원하는 것이 최소한의 코드로 세 배열의 요소를 출력하는 것이라면 모든 매개변수가 출력될 때까지 형식 문자열이 모든 매개변수에 순차적으로 적용된다는 사실을 사용할 수 있습니다 .
a=(1 2)
b=(3 4)
c=(5 6)
printf 'item is "%s"\n' "${a[@]}" "${b[@]}" "${c[@]}"
또 다른 방법은 좀 어색하지만하다중첩 루프의 경우 실제 배열을 반복하고 각 배열을 차례로 처리하는 것입니다. bash
쉘 에서는 루프를 통해 이 작업을 수행할 수 있습니다.이름이름 참조 변수가 있는 배열:
a=(1 2)
b=(3 4)
c=(5 6)
for arrayname in a b c; do
declare -n array="$arrayname"
for item in "${array[@]}"; do
printf 'item is "%s" (from original array "%s")\n' "$item" "$arrayname"
done
done
여기서 우리는 declare -n
변수가 array
현재 이름을 갖고 있는 모든 변수처럼 동작해야 한다고 종종 말합니다. arrayname
그런 다음 array
이를 배열인 것처럼 사용합니다. 이는 확장된 값이 $arrayname
배열의 이름이기 때문에 작동합니다.
이것은 다소 특이한 프로그래밍 방식 bash
이지만 작동합니다. 또한 별도의 배열 처리 함수를 도입하여 코드를 더 복잡하게 만들 수 있습니다(이 특별한 경우에는 이 코드를 작성하는 적절한 방법이 아닙니다. 단일 printf
명령문을 사용하고 루프를 전혀 사용하지 않는 것이 더 좋습니다. 위에 표시됨) :
a=(1 2)
b=(3 4)
c=(5 6)
process_array () {
local -n array="$1"
for item in "${array[@]}"; do
printf 'item is "%s" (from original array "%s")\n' "$item" "$arrayname"
done
}
for arrayname in a b c; do
process_array "$arrayname"
done
이는 "함수에 배열 전달"입니다(실제로 변수를 참조하는 로컬 이름이 있는 함수에서 배열 이름으로 사용되는 변수 이름 전달).
여기에는 몇 가지 제한 사항이 있습니다. 예를 들어, process_array
이름 참조 변수를 사용하여 다른 함수를 호출할 수 없습니다 array
. 당신은 또한 볼 수 있습니다bash 쉘 함수에는 순환 이름 참조가 있지만 ksh에는 없습니다.
답변2
✦ ~/
❯ cat nested.sh
a=(1 2)
b=(3 4)
c=(5 6)
for arr in "${a[@]}" "${b[@]}" "${c[@]}"
do
for e in "${arr[@]}"
do
echo $e
done
done
✦ ~/
❯ bash nested.sh
1
2
3
4
5
6
✦ ~/
❯