bash script2023. 7. 19. 08:48

 

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

 

sed에서 역슬래시-괄호를 이용하면 문자열에서의 영역을 구분할 수 있는데, 이를 이용해서 단순 문자열 대체를 넘어서 좀 더 복잡한 작업을 할 수 있다. 몇가지 예시를 보면 금방 감을 잡을 수 있을 것이다. sed를 이용한 기본적인 문자열 대체 등 일반적인 내용은 이전 게시물을 참고하자. 여기로

 

우선 dialog.txt 파일의 내용이 아래와 같다고 가정해 보자.

cat dialog.txt
John said, "Hi, Jane."
Jane replied, "Hello, John."
John said, "It's nice to see you."

위의 파일에 담긴 내용을 아래와 같이 바꾸고 싶다면 어떻게 할까?

John: Hi, Jane.
Jane: Hello, John.
John: It's nice to see you.

첫번째 어절은 그대로 두고, 두번째 어절(said, 또는 replied)은 콜론(:)으로 바꾸고, 세번째 이후 나머지 부분의 따옴표를 제거해야 한다. 이 작업을 sed의 's/문자열1/문자열2/' 옵션으로 해 보는 것이다.

먼저 dialog.txt의 영역 구분을 아래와 같이 해 볼 수 있다.

[이름] [공백] [쉼표로 끝나는 단어] [공백] [따옴표 안의 문장]

영역 구분은 역슬래시와 괄호를 이용해서 표시한다. \(영역\) 이런 형태다. 따라서, sed의 인자로 들어갈 때 아래와 같은 형태가 된다.

\(이름\) \(쉼표로 끝나는 단어\) "\(따옴표 안의 문장\)"

아직 끝나지 않았다. 따옴표(")의 경우 shell에서 처리되지 않도록 하기 위해 역슬래시를 앞에 붙여야 한다. 즉, 아래와 같이 되어야겠다.

\(이름\) \(쉼표로 끝나는 단어\) \"\(따옴표 안의 문장\)\"

알파벳 문자열을 지칭하는 정규표현식([[:alpha:]]*)과 임의의 문자열을 지칭하는 정규표현식(.*)을 이용해서 위의 영역 구분을 완성한다.

\([[:alpha:]]*\) \(.*,\) \"\(.*\)\"

일단 여기까지 하고 반쪽짜리 sed 명령을 보면 아래와 같다.

sed 's/\([[:alpha:]]*\) \(.*,\) \"\(.*\)\"/대체할 문자열/' dialog.txt

이제 위의 명령에서 "대체할 문자열" 부분을 지정하면 되겠다. 앞에서 구분한 영역을 지칭하는 형식은 역슬래시와 수자가 된다. 첫번째 영역은 \1, 두번째 영역은 \2, 이런 식이다. 위의 예시에서 첫번째 영역과 세번째 영역을 출력하되 중간에 콜론이 들어가게 하면 되므로 최종 명령어는 아래와 같이 된다.

sed 's/\([[:alpha:]]*\) \(.*,\) \"\(.*\)\"/\1: \3/' dialog.txt
John: Hi, Jane.
Jane: Hello, John.
John: It's nice to see you.

한 가지 더 생각해 보자. 만약 John said, "Hi, Jane." 이러한 형태의 문장을 아래와 같은 형태로 바꾸려면 어떻게 할까?

Hi, Jane. (John)

첫번째 영역과 세번째 영역의 위치를 바꾸고 괄호를 추가해 주면 된다. 즉, 아래와 같이 입력하면 되겠다.

sed 's/\([[:alpha:]]*\) \(.*,\) \"\(.*\)\"/\3 (\1)/' dialog.txt
Hi, Jane. (John)
Hello, John. (Jane)
It's nice to see you. (John)

인자 구성이 좀 복잡해 보이긴 하지만, 차근차근 해 보면서 기억해 두면 동일한 형실으로 표시된 대량의 문자열에 대해 반복작업을 해야 할 경우 상당히 요긴하게 활용할 수 있다.

 

728x90
Posted by 반달가면