배열(Array) 개념 없는 프로그래밍 언어를 상상하기 어렵습니다. 각 언어마다 구현 방식은 다르지만, 배열은 서로 같거나 다른 데이터들을 하나의 상징적인 이름 아래 통합하여 관리할 수 있게 해주는 강력한 도구입니다.

이 글에서는 셸 스크립팅 관점에서 배열 개념을 다루며, 배열을 활용한 다양한 셸 스크립트 예제를 통해 실전 감각을 익혀보겠습니다.
배열 초기화와 사용 방법
최신 버전의 bash는 1차원 배열을 지원합니다. 배열은 declare 셸 내장 명령어로 명시적으로 선언할 수 있습니다.
declare -a var
하지만 위와 같이 배열 변수를 반드시 선언해야 하는 것은 아닙니다. 다음과 같이 각 요소를 배열에 직접 삽입할 수도 있습니다.
var[XX]=<value>
여기서 'XX'는 배열 인덱스를 의미합니다. 배열 요소에 접근(역참조)할 때는 중괄호 문법을 사용합니다.
${var[XX]}참고: 배열 인덱스는 항상 0부터 시작합니다.
배열 전체를 한 번에 초기화하는 더 편리한 방법은 아래와 같이 괄호 쌍을 이용하는 것입니다.
var=( element1 element2 element3 . . . elementN )
또 다른 방식으로 배열에 값을 할당할 수도 있습니다. 이 초기화 방법은 앞서 설명한 방법의 하위 유형으로, 특정 인덱스에 직접 값을 지정하는 방식입니다.
array=( [XX]=<value> [XX]=<value> . . . )
read 셸 내장 명령어를 사용하면 스크립트 실행 중에 배열 값을 읽거나 할당할 수도 있습니다.
read -a array
스크립트 안에서 위 문장이 실행되면 입력을 기다립니다. 이때 배열 요소들은 공백으로 구분하여 입력해야 하며(줄바꿈이 아닌), 값 입력 후 Enter 키를 눌러 종료합니다.
배열 요소를 순회할 때는 for 루프를 활용할 수도 있습니다.
for i in "${array[@]}"do #access each element as $i. . .done 다음 스크립트는 지금까지 설명한 내용을 모두 정리한 예제입니다.
#!/bin/bash array1[0]=one array1[1]=1 echo ${array1[0]} echo ${array1[1]} array2=( one two three ) echo ${array2[0]} echo ${array2[2]} array3=( [9]=nine [11]=11 ) echo ${array3[9]} echo ${array3[11]} read -a array4 for i in "${array4[@]}" do echo $i done exit 0배열의 다양한 연산
표준 문자열 연산 대부분은 배열에도 그대로 적용됩니다. 다음 샘플 스크립트는 문자열 연산을 포함한 여러 배열 연산을 구현한 예제입니다.
#!/bin/bash array=( apple bat cat dog elephant frog ) #print first element echo ${array[0]} echo ${array:0} #display all elements echo ${array[@]} echo ${array[@]:0} #display all elements except first one echo ${array[@]:1} #display elements in a range echo ${array[@]:1:4} #length of first element echo ${#array[0]} echo ${#array} #number of elements echo ${#array[*]} echo ${#array[@]} #replacing substring echo ${array[@]//a/A} exit 0위 스크립트를 실행하면 다음과 같은 결과가 출력됩니다.
apple apple apple bat cat dog elephant frog apple bat cat dog elephant frog bat cat dog elephant frog bat cat dog elephant 5 5 6 6 Apple bAt cAt dog elephAnt frog
위 스크립트는 스스로 설명이 되는 코드이므로 자세히 짚지 않겠습니다. 필요하다면 이 시리즈의 별도 파트에서 문자열 조작만을 집중적으로 다룰 예정입니다.
배열과 명령 치환(Command Substitution)
명령 치환은 하나 또는 여러 명령의 출력 결과를 다른 컨텍스트에 할당하는 기능입니다. 배열의 맥락에서는 명령의 출력 결과를 배열의 개별 요소로 삽입할 수 있습니다. 문법은 다음과 같습니다.
array=( $(command) )
기본적으로 명령 출력 결과에서 공백으로 구분된 내용들이 각각 배열의 개별 요소로 들어갑니다. 다음 스크립트는 디렉터리 내용을 나열하되, 755 권한을 가진 파일들만 출력하는 예제입니다.
#!/bin/bash ERR=27 EXT=0 if [ $# -ne 1 ]; then echo "Usage: $0 <path>" exit $ERR fi if [ ! -d $1 ]; then echo "Directory $1 doesn't exists" exit $ERR fi temp=( $(find $1 -maxdepth 1 -type f) ) for i in "${temp[@]}" do perm=$(ls -l $i) if [ `expr ${perm:0:10} : "-rwxr-xr-x"` -eq 10 ]; then echo ${i##*/} fi done exit $EXT2차원 배열 흉내 내기
1차원 배열만으로도 2차원 행렬을 손쉽게 표현할 수 있습니다. 행 우선(row major order) 표현 방식에서는 행렬의 각 행에 있는 요소들이 순차적으로 배열 인덱스에 저장됩니다. m×n 행렬의 경우 이를 계산하는 공식은 다음과 같이 작성할 수 있습니다.
matrix[i][j]=array[n*i+j]
다음은 두 행렬을 더하고 결과 행렬을 출력하는 샘플 스크립트입니다.
#!/bin/bash read -p "Enter the matrix order [mxn] : " t m=${t:0:1} n=${t:2:1} echo "Enter the elements for first matrix" for i in `seq 0 $(($m-1))` do for j in `seq 0 $(($n-1))` do read x[$(($n*$i+$j))] done done echo "Enter the elements for second matrix" for i in `seq 0 $(($m-1))` do for j in `seq 0 $(($n-1))` do read y[$(($n*$i+$j))] z[$(($n*$i+$j))]=$((${x[$(($n*$i+$j))]}+${y[$(($n*$i+$j))]})) done done echo "Matrix after addition is" for i in `seq 0 $(($m-1))` do for j in `seq 0 $(($n-1))` do echo -ne "${z[$(($n*i+j))]} " done echo -e "
" done exit 0 셸 스크립팅에서 배열 구현에는 몇 가지 제약이 있지만, 특히 명령 치환을 다룰 때 등 소수의 상황에서 매우 유용하게 활용됩니다. 시스템 관리자의 관점에서 보면, 배열 개념은 GNU/Linux 시스템에서 수많은 백그라운드 스크립트가 개발되는 토대가 되었습니다.