sed 매칭에 성공한 행(行/줄/Line) 지우기, 그리고 다른 구분자(Delimiter) 사용

이걸 해결하느라 한시간은 헤맨 듯 하다. 그래도, 이제는 구글을 뒤지면 답을 얻을 수 있다. (엄밀하게 말해 ‘구글’을 뒤지는 일은 없지만..)

sed 에 대해 간단히 정리하면, 이런 문법을 사용해야 한다.

sed "s/regex/replacement/g" file

위 구문은, file 을 읽어서, Regular Expressions 를 통해 ‘regex’ 를 찾고, ‘replacement’ 로 바꾸라는 뜻이 된다.

여기서 / 를 Delimiter 라고 부르는데, 꼭 / 일 필요는 없다. 아무 문자나 사용해도 되지만, 같은 글자를 사용해야 한다.

즉, 다음과 같이 해도 된다.

sed "s_regex_replacement_g" file

밑줄이 아니라 어떤 문자를 사용해도 된다.

다만!!!!
‘regex’ 에 Delimiter 가 들어있는 경우, 오류가 발생한다.
다음을 보자.

$ sed 's/home/user/home/userY/g' <<< "home/user"
sed: -e expression #1, char 13: `s' 에 관한 알수 없는 옵션

home/user(regex) 를 home/userY(replacement) 로 바꾸고 싶었다. 그런데, regex 자체에 / 가 들어있기 때문에, sed 는 명령을 이해하기 어려운 상태가 됐다.
따라서 위와 같은 경우는 Delimiter 를 다음과 같이 바꿔주면, 원하는 결과를 얻을 수 있다.

$ sed 's_home/user_home/userY_g' <<< "home/user"
home/userY

여기까진 예전부터 알고 있던 내용인데…
아 젠장!


sed 에는, 매칭이 된 문자가 있는 을 삭제해버리는 기능도 있다. 매칭된 문자열만 삭제하는게 아니고, 매칭이 True 가 되는 행 자체를 지워버린다.

이 때 ‘d’ 명령을 쓰며, 자세한 설명은 또 누군가의 도움을 받아야 한다. (man page 에선 전혀 도움을 받을 수 없다. “d Delete pattern space. Start next cycle.” 이게 다다.)
형식은 다음과 같다.

sed '/pattern/d' file

바꾸기(Substitute) 와 비슷하지만, Delimiter 가 시작부터 나오는 게 다르다.

그런데, 상황이 위와 똑같았기 때문에, 즉, pattern 에 슬래시가 들어가기에, 저대로 적용하면 오류가 발생했다.

그리하여, 다른 문자로 바꿔봤는데..

$ sed "_pattern_d" "./file_a"
sed: -e expression #1, char 1: unknown command: `_'

왜 안되는거야.. delete 에는 안되는 거야???
Man Page 에서도 확실한 내용을 찾지 못해서 구글을 ‘통해’ 여기 저기 돌아다니기 시작.. 그리고 한 한시간 여??

을 찾아냈다. Comment 중, AlexR 님이 쓴 내용에 이런 표현이 있었다.

sed "\:$Line:d"

아!!!! ㅆ ㅏ ㅇ!
여기에서도 이스케이핑을 해줘야 하다니. 으아아아아아아!!!

아쉽게도 저 내용에 대한 문서는 찾지 못했다.
이 글을 쓰고 나서 한참 시간이 흐른 뒤(2021.1월 말), 제대로된 문서를 찾을 수 있었다.
man page 내용은 그저 수박 겉핥기일뿐, Gnu 설명서에 모든 내용이 들어 있었다.
그 부분만 옮겨보면 다음과 같다.

\%regexp%

(The % may be replaced by any other single character.)

This also matches the regular expression regexp, but allows one to use a different delimiter than /. This is particularly useful if the regexp itself contains a lot of slashes, since it avoids the tedious escaping of every /. If regexp itself includes any delimiter characters, each must be escaped by a backslash (\).

그리고, 위 글의 질문자의 글에서는, 아예 Delimiter 를 쓰지 않고도 됐다고 하는데..

sed -i "$LINE"'d' "$FILE"

나는 저렇게해선 성공하지 못했다.
아마도, $LINE 의 첫 행에 / 가 들어가 있어서 그런 모양이다.

어쨌든, 그래도 이 정도에서 해결할 수 있어서 다행이라고 해야 하려나.

Author: 아무도안

안녕하세요. 글 남겨주셔서 고맙습니다.