[bash: awk] 다수의 문자열을 검색하여 일치하는 부분만 출력하기(match, substr) 리눅스 bash script

우선, awk에서 match 함수와 substr 함수를 활용해서 특정 문자열 패턴을 검색하고 일치하는 부분만 출력하는 방법은 이전 게시물을 참고하자. 여기로.

일단 기본적인 예시는 아래와 같다. 행 전체($0)에서 문자열 "abc"가 있으면 일치하는 부분만 출력한다.

echo "abcdefg" | awk 'match($0,/abc/) { print substr($0,RSTART,RLENGTH) }'
abc

여기서는 입력에 대해 검색하고자 하는 문자열 패턴이 여러개일 경우를 생각해 보려고 한다. 예를 들어 탭(tab)을 항목 구분자(field separator)로 사용하는 입력에서  두번째 항목($2)에 문자열 "abc"가 있는지 확인하고 세번째 항목($3)에 3개의 연속된 수자(정규표현식 [0-9][0-9][0-9])가 있는지 확인해서, 첫번째 항목과 함께 일치하는 부분만 출력해야 하는 상황을 생각해 보자.

만약 입력된 행이 "1  abcde  1234"라면, 출력은 "1  abc  123" 이렇게 나와야 할 것이다.

만약 입력된 행이 "2  aabc  abc"라면, 세번째 항목에는 수자가 없기 때문에 출력은 "2  abc" 이렇게 나와야 할 것이다.

match 함수를 두번 사용하면 되는 것은 분명하므로, 일단 아래와 같이 시도해 볼 수 있을 것이다. -F 옵션을 이용해서 항목 구분자를 탭으로 지정했다.

echo -e "1\tabcde\t1234" | awk -F '\t' '{ print $1 }; match($2,/abc/) { print "\t" substr($2,RSTART,RLENGTH) }; match($3,/[0-9][0-9][0-9]/) { print "\t" substr($3,RSTART,RLENGTH) }'
1
  abc
  123

awk 스크립트 부분만 보기 편하게 다시 써 보면 아래와 같다.

{ print $1 };
match($2,/abc/) { print "\t" substr($2,RSTART,RLENGTH) };
match($3,/[0-9][0-9][0-9]/) { print "\t" substr($3,RSTART,RLENGTH) }

우선 첫번째 항목을 출력하고, 두번째 항목과 세번째 항목에 대해 각각 match 함수를 적용했다. 결과값은 괜찮으나 한줄로 모아서 출력해 주는 것이 보기에 깔끔하므로 print 대신 printf를 사용하여 줄바꿈이 나오지 않도록 해 보자. 이 경우엔 결과값을 출력한 후 마지막에 줄바꿈을 수동으로 추가해 주어야 한다. awk 스크립트 부분만 써 보면 아래와 같이 될 것이다.

{ printf $1 };
match($2,/abc/) { printf "\t" substr($2,RSTART,RLENGTH) };
match($3,/[0-9][0-9][0-9]/) { printf "\t" substr($3,RSTART,RLENGTH) };
{ printf "\n" }

따라서, 위의 예시는 아래와 같이 고치면 된다.

echo -e "1\tabcde\t1234" | awk -F '\t' '{ printf("%s",$1) }; match($2,/abc/) { printf("%s","\t" substr($2,RSTART,RLENGTH)) }; match($3,/[0-9][0-9][0-9]/) { printf("%s","\t" substr($3,RSTART,RLENGTH)) }; { printf "\n" }'
1  abc  123

test.txt 파일에 저장된 내용에 대해 이러한 작업을 한다고 가정하면 아래와 같이 된다.

awk -F '\t' '{ printf("%s",$1) }; match($2,/abc/) { printf("%s","\t" substr($2,RSTART,RLENGTH)) }; match($3,/[0-9][0-9][0-9]/) { printf("%s","\t" substr($3,RSTART,RLENGTH)) }; { printf "\n" }' test.txt

마지막으로, 입력에서 조건에 맞는 부분이 전혀 없을 경우에는 첫번째 항목만 출력될텐데 이 경우에 아예 행이 출력되지 않도록 하고 싶다면 출력을 파이프(|)로 넘겨서 grep이나 awk로 적당히 선별해 주면 되겠다. 위의 예시에서는 하나 이상 조건에 맞는 부분이 있다면 항목 구분자인 탭이 출력될 것이므로 출력값에서 탭을 포함하고 있는 것만 추려낼 수 있다.

awk -F '\t'  '{ printf("%s",$1) }; match($2,/abc/) { printf("%s","\t" substr($2,RSTART,RLENGTH)) }; match($3,/[0-9][0-9][0-9]/) { printf("%s","\t" substr($3,RSTART,RLENGTH)) }; { printf "\n" }' test.txt | awk '/\t/'



덧글

댓글 입력 영역
* 비로그인 덧글의 IP 전체보기를 설정한 이글루입니다.

Google Analytics


B-Side


adsense(w160_h600)2

통계 위젯 (화이트)

605300
3990
1845249

ad_widget_2