1. 사용 명령어 |
(1) getopts
(2) shift
(3) awk
(4) grep
(5) sed
2. 키워드 & 사용처 |
(1) 키워드
옵션, 자릿수, 스페이스 제거, 우편번호
(2) 사용처
우편번호나 전화번호 같은 텍스트에서 정해진 자리에 하이픈을 넣거나 삭제하고 싶을 때 사용합니다.
3. 실행 예제 |
$ cat number-nohyphen.txt
# 숫자뿐인 우편번호
562001
2250022
A1200B1
$ ./num-hyphen.sh number-nohyphen.txt
# 하이픈 추가
561-0001
225-0022
$ cat number-hyphen.txt
# 하이픈이 있는 우편번호
562-0001
325-10022
362-0001
A1B-0C1C
$ ./number-hyphen.sh -d number-hyphen.txt
# 하이픈 제거
5620001
3620001
4. 스크립트 |
#!/bin/sh
# 하이픈 삭제 여부 플래그. 1이면 삭제
d_flag=0 ①
# getopts 명령어로 삭제 옵션(-d) 판별
while getopts "d" option ②
do
case $option in
d)
d_flag=1
;;
\?)
exit 1
;;
esac
done
# 명령행 인수로 지정한 우편번호 파일을
# 셸 변수 filename에 대입
shift $(expr $OPTIND - 1) ③
filename="$1"
# 지정한 우편번호 파일 확인
if [ ! -f "$filename" ]; then ④
echo " 대상 파일이 존재하지 않습니다: $filename" >& 2 ④
exit 1 ④
fi
# d_flag가 지정되면 하이픈 삭제. 아니면 하이픈 추가
if [ "$d_flag" -eq 1 ]; then ⑤
# *하이픈 삭제
# awk로 앞뒤 공백 제거 -> 포맷 학인 -> 하이픈 삭제
awk '{print $1}' "$filename" | grep '^[0-9]\{3\}-[0-9]\{4\}$' | sed "s/-//" ⑥
else
# *하이픈 추가
# awk로 앞뒤 공백 제거 -> 포맷 확인 -> 하이픈 추가
awk '{print $1}' "$filename" | grep '^[0-9]\{7\}$' | sed "s/\(...\)/\1-/" ⑦
fi
5. 해설 |
이 스크립트는 7자리 숫자가 적힌 파일에서 3번째와 4번째 숫자 사이에 하이픈을 넣거나, 하이픈이 있는 7자리 숫자에서 하이픈을 삭제해서 표시합니다. 스크립트 옵션으로 -d를 지정하면 하이픈을 삭제하고 아니면 추가합니다. 우편번호를 비롯한 숫자 텍스트에 응용할 수 있습니다.
number-nohyphen.txt라는 하이픈이 없는 7자리 숫자(5620001 같은) 파일과 number-hyphen.txt라는 하이픈이 있는 '세 자리 숫자-네 자리 숫자(562-0001)' 파일을 다룬다고 가정합니다.
스크립트로 하이픈을 추가할 때는 다음과 같이 텍스트 파일을 다룹니다.
1. 각 줄의 앞 뒤에 스페이스가 있으면 제거한다.
2. 7자리 숫자가 아니라면 포맷 에러로 보고 무시한다.
하이픈을 삭제할 때는 다음과 같은 방법을 사용합니다.
1. 각 줄의 앞 뒤에 스페이스가 있으면 제거한다.
2. '3자리숫자-4자리숫자'가 아니라면 포맷 에러로 보고 무시한다.
이런 종류의 스크립트를 작성할 때면 '입력 텍스트 파일의 포맷에 맞지 않은 데이터를 어떻게 처리할까' 라는 문제가 있는데 여기에서는 단순히 무시하도록 합니다.
우선 ①에서 옵션 지정 플래그 변수 d_flag를 정의합니다. -d 옵션(하이픈 제거)이 지정되었는지 판별하는 변수입니다. ②는 getopts 명령어를 사용해서 실행할 때 -d 옵션이 지정되었는지 판별해서 지정했다면 1을 셸 변수 d_flag에 대입합니다.
③은 우선 위치ㅍ파라미터에서 명령행 인수로 지정한 옵션을 shift 명령어로 당깁니다. 이러면 위치 파라미터 $1에 명령행 인수로 지정한 파일명이 저장되므로 $1을 셸 변수 filename에 대입합니다.
④에서 지정한 우편번호 파일이 존재하는지 확인합니다. 부정 연산자 !와 일반 파일인지 확인하는 -f 연산자를 함께 써서 파일이 존재하지 않거나 디렉터리 등이라면 에러를 표시하고 종료합니다.
⑤는 하이픈을 삭제할지 추가할지 if문으로 판단해서 분기합니다. -d 옵션이 지정되었으면 셸 변수 d_flag가 1이므로 하이픈을 삭제하는 ⑥ 처리로 분기합니다. -d 옵션 없다면 d_flag가 0이라서 if문은 거짓이 되고 하이픈을 추가하는 ⑦ 처리가 됩니다.
⑥은 우선 앞뒤 스페이스를 제거하기 위해 awk 명령어로 첫 번째 컬럼을 {print $1}로 표시합니다. 텍스트 앞 뒤에 스페이스가 있다면 이렇게 해서 간단히 제거할 수 있습니다.
이어서 awk 명령어로 하이픈을 넣은 다음 grep 명령어로 포맷을 확인합니다. 여기에서 \{3\}을 사용합니다. 이것은 패턴이 몇 번 출현하는지 나타내는 정규표현식으로 \{\}으로 싼 숫자 횟수만큼 직전 문자가 반복해서 나올 때 일치하게 됩니다.
grep 'e\{2\}' -> ee와 일치, grep "ee"와 동일
grep '[a-zA-Z]\{8\}' -> 영문자 8글자
여기에서 우선 [0-9]로 숫자를 의미하는 문자 클래스를 지정하고, 그 뒤에 \{3\}이라고 세번 나오는 패턴을 하이픈으로 이어서 [0-9]\{3\}-[0-9]\{4\}를 사용합니다. 이것은 '세 자리 숫자 뒤에 하이픈이 나오고 다시 네 자리 숫자가 옴'이란 패턴입니다. 여기에 일치하지 않는 줄은 포맷 에러이므로 표시하지 않도록 무시합니다.
⑥ 마지막에 sed 명령어로 하이픈을 삭제합니다. sed 명령어로 문자를 삭제하려면 캐릭터를 지정해서 빈 문자열로 치환하면 되므로 "s/-//"라고 적으면 하이픈을 제거할 수 있습니다.
-d 옵션을 지정하지 않으면 ⑦처리로 분기합니다. 여기서는 하이픈을 추가하는 처리를 합니다. ⑥처럼 앞뒤 스페이스를 제거하기 위해 awk 명령어로 {printf $1}을 한다음, [0-9]\{7\}라는 포맷과 일치하는지 확인하는 grep 명령어를 실행합니다. 7자리 숫자가 등장하지 않으면 무시하게 됩니다.
⑦ 마지막에 sed 명령어로 하이픈을 추가합니다. 여기에는 7자리 숫자 문자열이 넘어오므로 "앞에서부터 세자리 뒤에 하이픈을 추가"라는 처리를 하기 위해 우선 앞 세 자리를 \(...\)로 지정하여 후방참조가 가능하도록 합니다. 그런 다음 하이픈을 추가하면 되므로 치환 후 문자열은 후방참조 \1을 사용해서 \1-으로 치환하면 됩니다.
이렇게 하면 숫자 문자열을 가지고 우편번호 포맷 일치 확인과 하이픈 삭제 및 추가를 할 수 있습니다.
<주의사항>
이 예제에서는 포맷과 일치하지 않는 에러를 무시하고 있지만 실제로 사용하려면 에러를 표시하거나 스크립트를 종료하는 등 상황에 따른 설계가 필요합니다.
참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전
'IT 이야기 > Linux 셸 스크립트' 카테고리의 다른 글
[Linux 셸 스크립트] 텍스트 처리 - 084 텍스트 파일에서 HTML 파일 만들기 (0) | 2021.04.13 |
---|---|
[Linux 셸 스크립트] 텍스트 처리 - 083 파일 크기를 줄이기 위해 자바스크립트 파일에서 빈 줄 제거하기 (0) | 2021.04.13 |
지역화폐 147탄 - 경남 하동군(하동사랑상품권, 모바일 하동사랑상품권) (0) | 2021.04.13 |
[Linux 셸 스크립트] 텍스트 처리 - 081 오른쪽 정렬로 숫자를 표시하는 텍스트 표 만들기 (0) | 2021.04.12 |
[Linux 셸 스크립트] 텍스트 처리 - 080 sed로 HTML 파일 속성을 바꿀 때 슬래시 이스케이프 피하기 (0) | 2021.04.12 |
댓글