adsense_in_article_test


[bash: for, sed, echo] txt 파일에서 여러줄로 된 항목을 한줄로 바꾸기 리눅스 bash script

파일에서 특정한 문자열을 검색해야 하는데 하나의 항목에 대한 내용이 여러줄로 되어 있는 경우가 있다. 예를 들어 전화번호부에서 특정인물의 전화번호를 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



핑백

  • 반달가면 : [bash: tr, sed] txt 파일에서 여러줄로 된 항목을 한줄로 바꾸기 - 2 2015-04-30 22:51:50 #

    ... 명령과 for 반복문을 이용해서 여러줄로 된 항목을 한줄로 바꾸는 방법을 써 둔 적이 있는데, 그보다 좀 더 우아한 방법을 찾아냈다. (어쨌든 이전에 적어놓은 방법은 여기로) 우선 tr 명령의 기본적인 사용법을 잠깐 살펴 보자. 특정 캐럭터 집합을 다른 캐럭터 집합으로 대체하는 기능을 제공한다. 아래의 예시를 보면 금방 감을 잡을 ... more

덧글

  • yarra 2015/03/07 09:34 # 삭제 답글

    vi에서 하시면 좀 더 간단합니다.

    :%s/^phone/tphone/g ==> phone 앞에 탭을 붙임
    :%g/^name/j ==> name으로 시작하는 줄을 다음 줄과 합침(한 아이템을 한줄로 만듬)
    :%g/^$/d ==> 빈줄 제거
  • 반달가면 2015/03/08 01:39 #

    아 네. 제 경우엔 매우 많은 수의 파일에 대해 동일한 작업을 반복해야 되는 상황이 종종 있어서 스크립트로 해결하고 있습니다.
댓글 입력 영역
* 비로그인 덧글의 IP 전체보기를 설정한 이글루입니다.



통계 위젯 (화이트)

168516
2895
2275626

2019 대표이글루_IT

B-Side