1. 사용 명령어 |
(1) echo
2. 키워드 & 사용처 |
(1) 키워드
파라미터 확장, 문자열, 치환, sed
(2) 사용처
변수 내부 문자열을 sed 명령어를 사용하지 않고 치환하고 싶을 때 사용합니다.
3. 실행 예제 |
$ ./bash-where.sh perl
/opt/local/bin/perl
/usr/bin/perl
4. 스크립트 |
#!/bin/bash
# 조사할 명령어 얻기
command="$1" ①
# 인수 확인
if [ -z "$command" ]; then ②
echo "에러: 조사 대상 명령어를 지정하세요." >&2
exit 1
fi
# 환경 변수 $PATH의 :을 스페이스로 치환, for문 반복해서 사용
for dir in ${PATH//:/ } ③
do
if [ -f "${dir}/${command}" ]; then
echo "${dir}/${command}"
fi
done
5. 해설 |
이 스크립트는 명령행 인수로 지정한 명령어가 환경 변수 경로에 있는지 탐색해서 존재하면 그 경로를 나열합니다. 실행 예에서 perl 명령어로 /opt/local/bin과 /usr/bin 두 곳에서 발견했다는 걸 알 수 있습니다.
예제에서는 tcsh라는 셸의 where 명령어를 모방한 스크립트를 작성합니다. tcsh는 bash와 다른 계열의 C 셸 일종으로 BSD계 유닉스에서 자주 사용했습니다. tcsh에는 어떤 명령어가 경로 어디에 존재하는지 모두 나열하는 where라는 명령어가 있습니다.
bash는 where 명령어가 없기 때문에 스크립트로 작성해보겠습니다. 예를 들어 펄이 시스템에 달느 경로로 복수 개 설치되어 있으면 그 상태를 확인하기 위해 사용하는 툴로 편리하겠지요.
①에서 명령행 인수로 지정한 명령어를 위치 파라미터 $1에서 셸 변수 command에 대입합니다. ②는 그 인수 내용을 확인해서 빈 문자열인지 test 명령어 -z 옵션으로 확인합니다. 빈 문자열이면 명령어가 지정되어 있지 않으므로 에러를 표시하고 exit 명령어로 종료합니다.
③에서 bash 파라미터 확장 기능을 써서 :(콜론)을 스페이스로 치환합니다. 이런 문자열 치환은 일반적으로 sed 명령어를 사용하지만 bash에서는 표준 기능인 파라미터 확장으로 치환할 수 있어 외부 명령어인 sed를 사용하지 않아도 됩니다.
bash 파라미터 확장을 사용한 문자열 치환은 다음과 같은 서식을 이용합니다.
1. ${변수명/패턴/치환문자열}
[변수명]의 마지막 일치한 [패턴]만 [치환문자열]로 바꿉니다. sed 명령어의 's/패턴/치환문자열/'에 해당합니다.
2. ${변수명//패턴/치환문자열}
[변수명]의 일치한 모든 [패턴]을 [치환문자열]로 바꿉니다. sed 명령어의 's/패턴/치환문자열/g'에 해당합니다.
패턴 지정은 와일드 카드인 *(임의 문자열)와 ?(임의 한 문자), 문자 클래스 지정[...] 등을 사용할 수 있습니다.
③에서 이용하는 변수 PATH는 명령어 경로 탐색을 지정하는 환경 변수로 다음처럼 콜론을 구분자로 지정합니다.
$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
콜론을 스페이스로 치환한 디렉터리 목록을 for문에 넘겨서 셸 변수 dir에 대입합니다. 각각의 경로에 명령행 인수로 지정한 명령어가 존재하는지 test 명령어 파일 확인 연산자 -f를 이용해서 확인하고 파일이 있으면 echo 명령어로 표시합니다.
이렇게 해서 명령어가 존재하는 모든 경로를 한 번에 표시할 수 있습니다. 같은 명령어가 여러 경로에 설치되어 있는지 확인하는 목적으로 사용할 수 있습니다.
<주의사항>
이 스크립튼느 for문에서 스페이스 구분자를 사용하므로 환경 변수 PATH에 스페이스를 포함한 디렉터리를 지정하면 제대로 동작하지 않습니다.
파라미터 확장을 사용할 수 없는 sh 스크립트는 변수 내부 문자열을 치환할 때 다음처럼 echo 명령어로 변수값을 출력해서 sed 명령어로 처리할 필요가 있습니다.
echo $PATH | sed 's/:/ /g'
문자열 치환 시 문자열 앞부분만 일치하는 /#이라는 표기법도 있습니다. 이것은 정규표현식에서는 ^로 표시하는 패턴입니다. 다음처럼 앞부분에 필요 없는 스페이스가 들어 있는 문자열과 없는 문자열이 있을 때 /#으로 치환하면 앞부분 스페이스가 있는 문자열은 치환되지 않습니다.
# 앞부분에 필요 없는 스페이스가 있음
str1=" http://www.example.com/"
# 스페이스가 없음
str2="http://www.example.com/"
echo ${str1/#http:/hxxp:}
echo ${str2/#http:/hxxp:}
다음처럼 첫 번째 셸 변수 str1은 앞부분에 스페이스가 있어서 일치하지 않는다는 걸 알 수 있습니다.
http://www.example.com/
hxxp://www.example.com/
그리고 이 외에는 반대로 끝 부분에서 일치하고 싶을 때는 /% 표기법을 사용합니다.
참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전
'IT 이야기 > Linux 셸 스크립트' 카테고리의 다른 글
[Linux 셸 스크립트] bash - 130 파이프 처리로 각 명령어 종료 상태값 조사하기 (0) | 2021.07.13 |
---|---|
[Linux 셸 스크립트] bash - 129 중간 파일 없이 명령어 출력을 파일처럼 다루기 (0) | 2021.07.06 |
[Linux 셸 스크립트] bash - 127 변수 내부 문자열을 n 번째부터 m 번째까지 추출하기 (0) | 2021.07.06 |
[Linux 셸 스크립트] bash - 126 사칙 연산을 간단하게 작성하기 (0) | 2021.07.06 |
[Linux 셸 스크립트] bash - 125 for 반복문을 간단히 작성하기 (0) | 2021.07.06 |
댓글