bash script2023. 4. 11. 11:42

 

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

 

파일에서 특정한 문자열을 검색해야 하는데 하나의 항목에 대한 내용이 여러줄로 되어 있는 경우가 있다. 예를 들어 전화번호부에서 특정인물의 전화번호를 grep 명령으로 찾으려는데 아래와 같이 생긴 경우다.

cat my_file.txt
name: john
phone: 010-123-4556

name: jane
phone: 010-345-1234
...

리눅스에서 검색을 염두에 두고 있다면 처음부터 이런 형식으로 만들지 않는 것이 좋겠지만, 특정 어플리케이션의 출력이 원래 저런 형태를 띠고 있을 때도 있고 아무튼 위와 같은 형태의 파일을 다룰 일이 간혹 생기다 보니, 아래와 같은 스크립트를 사용하고 있다. 반복되는 항목이 여러줄로 나타날 경우 한 항목당 한줄씩으로 바꾸는 방법이다. 위에서 언급한 my_file.txt 파일을 가지고 이름과 전화번호를 한줄에 넣고 탭(tab)으로 구분되도록 만든다.

# 결과 파일명을 res_file 변수에 할당
res_file="my_file.modified.txt"
# sed 명령에 사용하기 위한 변수 prt
prt="p"
# my_file.txt가 몇줄인지 파악하여 max_line 변수에 할당
max_line=`cat my_file.txt | wc -l`
# my_file.txt 파일을 한줄씩 읽기 위한 for 반복문
for line_num in `seq 1 $max_line`
do
  # line_num번째 행을 cur_line 변수에 할당
  cur_line=`sed -n $line_num$prt my_file.txt`
  # 항목 구분자가 빈 줄이므로 빈 줄이 나타났는지 확인
  separator_check=`echo $cur_line | grep [[:graph:]] | wc -l`
  # separator_chek 변수값이 0이면 빈 줄이므로 줄바꿈, 아니면 줄바꿈 없이 현재 행을 추가하고 탭 추가
  if [[ $separator_check -eq 0 ]]
    then echo -e "\n" >> $res_file
    else echo -en "$cur_line\t" >> $res_file
  fi
done

파일을 한줄씩 읽어서(sed 명령), 빈 줄이면 줄바꿈을 추가하고(echo -e "\n") 아니면 해당 줄의 내용을 추가하되 줄바꿈 없이 탭을 추가하도록(echo -en "$cur_line\t") 한 것이다.  sed 명령에 대한 좀 더 자세한 내용과 echo 명령의 옵션은 이전 게시물을 참고하자. sed 명령에 대한 내용은 여기로, echo 명령에 대한 내용은 여기로.

항목 사이의 경계가 빈 줄이 아니라 다른 문자열이라면 구분자 확인을 위한 separator_chek 변수값을 할당 할 때 그에 맞게 grep 명령과 이후의 if 조건문을 바꿔 주면 되겠다. 예를 들어 my_file.txt에서 빈 줄이 없다면 항목 시작 문자열을 이용할 수 있다. 여기서는 "name:"이므로, 해당 부분이 아래와 같이 바뀌어야 할 것이다.

  separator_check=`echo $cur_line | grep "^name: " | wc -l`
  if [[ $separator_check -eq 1 ]]
    then echo -en "\n$cur_line\t" >> $res_file
    else echo -en "$cur_line\t"
  fi
    ...
 
위와 같이 작업해서 my_file.modified.txt 파일을 만들고 나면 좀 더 쉽게 검색을 할 수 있다.

# john의 전화번호 찾기
cat my_file.modified.txt | grep john
name: john    phone:  010-123-4556

728x90
Posted by 반달가면