bash script2023. 10. 10. 21:29

 

반달가면 이글루에서 백업 - http://bahndal.egloos.com/623017

우선, 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/' 

728x90
Posted by 반달가면