25장. 리스트(List Constructs)

"and list""or list"는 여러 명령어들을 연속적으로 실행시킬 수 있게 해줍니다. 이걸로 아주 복잡하게 중첩돼 있는 if/then이나 case 문을 효과적으로 대치할 수 있습니다.

명령어들을 묶기

and list

command-1 && command-2 && command-3 && ... command-n
각 명령어들은 바로 앞의 명령어가 true(0) 값을 리턴하는 동안 차례대로 실행됩니다. false(0이 아닌 값)가 처음 리턴될 때, 전체 명령어 사슬이 끊어지면서 종료됩니다(false를 처음 리턴한 명령어가 마지막으로 실행되는 명령어가 됩니다).

예 25-1. "and list"를 써서 명령어줄 인자 확인하기

#!/bin/bash
# "and list"

if [ ! -z "$1" ] && echo "첫번째 인자 = $1" && [ ! -z "$2" ] && echo "두번째 인자 = $2"
then
  echo "두 개 이상의 인자가 넘어왔습니다."
  # 모든 명령어 사슬이 참을 리턴했을 경우.
else
  echo "두 개 미만의 인자가 넘어왔습니다."
  # 명령어 사슬중 최소 하나가 거짓을 리턴.
fi  
# 주의할 게 하나 있습니다.
# if [ ! -z $1 ] 는 잘 되지만 똑같을 것 같은
# if [ -n $1 ] 는 잘 안 됩니다. 
# 하지만 
#  if [ -n "$1" ] 
# 처럼 쿼우트를 걸면 됩니다. 조심해서 쓰세요!
# 테스트에서 쓰이는 변수는 항상 쿼우트를 해서 쓰세요.


# "순수한" if/then 문을 써서 똑같은 일을 합니다.
if [ ! -z "$1" ]
then
  echo "첫번째 인자 = $1"
fi
if [ ! -z "$2" ]
then
  echo "두번째 인자 = $2"
  echo "두 개 이상의 인자가 넘어왔습니다."
else
  echo "두 개 미만의 인자가 넘어왔습니다."
fi
# 이 방법은 "and list"를 쓰는 것보다 더 길고 덜 세련돼 보입니다.


exit 0

예 25-2. "and list"를 써서 명령어줄 인자를 확인하는 다른 방법

#!/bin/bash

ARGS=1        # 원하는 인자 수.
E_BADARGS=65  # 틀린 인자 수일 경우의 종료값.

test $# -ne $ARGS && echo "사용법: `basename $0` $ARGS argument(s)" && exit $E_BADARGS
# condition-1 이 참이면(틀린 인자 갯수) 같은 줄의 나머지 부분이 실행되고 스크립트가 종료됨.

# 다음 줄은 위의 테스트가 실패할 경우에만 실행됩니다.
echo "인자 갯수가 맞습니다."

exit 0

# 종료값을 확인하려면 이 스크립트가 종료된 다음 "echo $?"를 해 보세요.
or list

command-1 || command-2 || command-3 || ... command-n
각 명령어들은 바로 앞의 명령어가 false를 리턴하는 동안 차례대로 실행됩니다. false가 처음 리턴될 때, 전체 명령어 사슬이 끊어지면서 종료됩니다(true를 처음 리턴한 명령어가 마지막으로 실행되는 명령어가 됩니다). 이는 분명히 "and list"와 정반대로 동작합니다.

예 25-3. "or lists""and list"를 같이 쓰기

#!/bin/bash

# "Delete", 별로 정교하지 않은 파일 지우기 유틸리티.
# 사용법: delete filename

E_BADARGS=65

if [ -z "$1" ]
then
  echo "사용법: `basename $0` filename"
  exit $E_BADARGS
fi  


file=$1  # 파일이름을 세트.

[ ! -f "$1" ] && echo "\"$1\" 파일을 찾을 수 없습니다. \
존재하지 않는 파일은 지울 수 없습니다."
# 파일이 존재하지 않을 때 에러 메세지를 내기 위해 AND LIST 사용.
# 두 줄에 걸친 echo 메세지 중간의 뉴라인을 이스케이프 시켰습니다. 잘 보세요.

[ ! -f "$1" ] || (rm -f $1; echo "File \"$file\" deleted.")
# OR LIST 를 써서 파일이 존재하는 경우에는 파일을 삭제.
# ( command1 ; command2 ) 는 사실, AND LIST 의 다른 버전입니다.

# 로직이 뒤바뀐 것에 주의하세요.
# AND LIST 는 참일 때 실행되고, OR LIST 는 거짓일 때 실행됩니다.

exit 0

경고

"or list"에 들어 있는 첫번째 명령어가 true를 리턴해야 동작합니다.

중요: and listor list종료 상태는 마지막으로 실행된 명령어의 종료 상태를 가져갑니다.

"and""or" list를 아주 멋지게 연결해서 쓸 수도 있지만 그렇게 되면 전체 로직이 뒤죽박죽되기 쉽고 디버깅할 때 아주 힘들어 집니다.
false && true || echo false    # false

# 똑같습니다.
( false && true ) || echo false     # false
# 하지만 이건 다르네요.
false && ( true || echo false )     # (아무것도 echo되지 않죠)

# 중요한 것은, 논리 연산자인 "&&"와 "||"가 같은 우선 순위를 갖기 때문에
# 왼쪽에서 오른쪽으로 그룹을 지어 전체를 평가해야 합니다.

# 뭘 어떻게 하고 있는지 모른다면 이렇게 복잡하게 쓰지 않는것이 좋습니다.

# Thanks, S.C.

변수를 테스트해보기 위해서 and / or list를 쓰는 예제는 예 A-6를 참고하세요.