bash script2023. 9. 8. 13:17

 

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

몇개의 문자열에 대한 검색은 기본적인 grep 명령으로 그 자리에서 작업을 해도 큰 문제가 없을 것이다.(grep을 이용한 다중 문자열 검색은 이전 게시물을 참고하자. 여기로)

# my_data.txt에서 문자열 abc 또는 123이 포함된 행 출력
cat my_data.txt | grep "abc\|123"

그러나, 꽤 많은 검색어가 있고 이 검색어들을 제외한 나머지 내용을 찾고자 할 때는 문제가 좀 복잡해 진다. 예를 들어 keyword.txt 파일에 10개 이상의 검색어가 저장되어 있고, my_data.txt 파일에서 이 검색어를 포함 또는 제외한 내용을 출력해야 하는 경우다. 일일이 수작업으로 확인하기 검색해야할 문자열이 너무 많다.

이럴 경우엔 배열(array)을 이용해서 검색어를 저장한 후에 검색어들을 "\|" 기호로 연결해서 grep에 사용할 인자(argument)를 만들어 주면 좀 더 편리하다. (사실 이것도 좀 귀찮은 방법이지만 검색어가 많을 때는 일일이 수작업으로 하는 것보다는 그나마 낫다 -_-;)

# keyword.txt 파일 내용 확인
cat keyword.txt
abc
123
...

만약 keyword.txt 파일에 있는 검색어에 공백(space)이 포함되어 있지 않다면 일은 조금 간단해 진다. 아래와 같이 배열을 이용해서 작업하면 되겠다. (배열에 대한 기본적인 내용은 이전 게시물을 참고하자. 여기로)

# keyword.txt 파일의 내용을 배열 kword_arr에 저장 (내용에 공백 없음)
kword_arr=(`grep [[:graph:]] keyword.txt`)
# grep에 사용할 인자를 생성하여 변수 grep_arg에 할당
grep_arg=`echo "${kword_arr[*]}" | sed 's/ /\\\|/g'`

# grep_arg의 값 확인
echo "$grep_arg"
abc\|123\|...

혹시 keyword.txt 파일에 문자열이 없는 빈 행이 있을 경우에 대비해서 cat 명령 대신 grep으로 유효한 문자열만 선별하도록 했다. 이제 대상 파일에 대해 검색을 하면 되겠다.

# my_data.txt 파일에서 keyword.txt 파일의 검색어를 포함한 내용을 출력
grep "$grep_arg" my_data.txt

# my_data.txt 파일에서 keyword.txt 파일의 검색어를 모두 제외한 나머지를 출력
grep -v "$grep_arg" my_data.txt

만약 검색어에 공백이 포함되어 있다면, 위와 같이 배열에 할당하면 공백과 줄바꿈을 모두 구분자로 사용하게 되므로 문제가 생긴다. 줄바꿈만 구분자로 사용하도록 필드 구분자 변경이 필요하다. (필드 구분자 변경에 대한 내용은 이전 게시물을 참고하자. 여기로)

# 기존 내부 필드 구분자(internal field separator) 백업
IFS_backup="$IFS"
# IFS값을 줄바꿈으로 설정
IFS=$'\n'
# keyword.txt 파일의 내용을 배열 kword_arr에 저장
kword_arr=(`grep [[:graph:]] keyword.txt`)
grep_arg=`echo "${kword_arr[*]}" | tr '\n' '\t' | sed 's/\t/\\\|/g'`
# IFS 원상복구
IFS="$IFS_backup"

위에서 변수 grep_arg의 값을 할당하는 부분을 보자. 공백이 없는 경우보다 복잡해졌다.

우선 echo 명령으로 배열에 저장된 값을 출력할 때 반드시 따옴표(")를 사용해야 함에 유의. 그래야 앞에서 새로 설정한 IFS 값이 적용된다(따옴표가 없으면 줄바꿈이 없이 공백을 구분자로 하여 출력된다).

그런 후에 tr 명령으로 줄바꿈(\n)을 탭(tab, \t)으로 바꾸고, sed 명령으로 탭을 "\|" 기호로 바꿔 주었다. 당연히 keyword.txt 파일에 저장된 검색어에 탭이 포함되어 있으면 이 방법을 사용할 수 없음에 유의. 

728x90
Posted by 반달가면