Ubuntu 14.04 LTS 환경을 기준으로 작성되었습니다.
sed
스트림 에디터라 부르며 지정한 지시에 따라 파일이나 파이프라인 입력을 편집해서 출력해주는 명령어
옵션
- -e: 하나의 지시(여러 번 지정 가능)
- -r: 확장 정규 표현식 사용(단, GNU 환경에서만 사용가능하고, OS X나 BSD 환경에서는 -E를 사용)
예시
$ echo "ccc" | sed -e "1i aaa" -e "1i bbb"
aaa
bbb
ccc
$ cat test.txt | sed -e "4d" -e "6i abc" -e "s/dog/cat/" > result.txt
: test.txt
에서 "dog"를 "cat"로 치환 => 6번째 줄에 "abc"를 삽입 => 4번째 줄을 제거한 결과를 result.txt
파일에 출력
$ cat test.txt | sed -e "s/abc/def/gi" > result.txt
: test.txt
에서 "abc"를 "def"로 치환(g: 한 줄 안에서 해당하는 모든 부분 치환, i: 대소문자 차이 무시)한 결과를 result.txt
파일에 출력
원본 파일에 출력하기
위에서 주목해야할 점은 기존의 원본 파일 test.txt
이 아닌 result.txt
파일에 출력한다는 점이다. 만약 result.txt
이 아닌 test.txt
파일로 리다이렉트를 해보면 test.txt
의 내용이 모두 사라지는 비극을 경험하게 될 것이다.
이는 sed
명령어 만의 문제가 아니라 하나의 명령어열에서 파일을 여는 조작과 기록하는 조작을 동시에 하였기 때문에 발생한 문제로, 그 결과 해당 파일의 내용이 모두 사라지는 경우가 생긴다.
만약 기존의 파일에 덮어쓰고 싶다면 별도의 스크립트를 작성하여 해결할 수 있다.
#!/bin/bash
# sed.sh
source=$1
tempfile="tempfile"
mv $source $tempfile
cat $tempfile | sed -e "4d" -e "6i abc" -e "s/dog/cat/" > $source
rm $tempfile
$ sh sed.sh test.txt
정규 표현식 이용하기
정규 표현식을 이용하여 치환할 수도 있다. 하지만 이 때 리눅스 환경에 따라 옵션 이름이 다름에 주의하자.
#!/bin/bash
# expr.sh
case "$(uname)" in
Darwin|*BSD) sed="sed -E" ;; # OS X 또는 BSD 환경
*) sed="sed -r" ;; # GNU 환경
esac
expr="s/(dog|cat|lion)/tiger/"
source=$1
tempfile="tempfile"
mv $source $tempfile
cat $tempfile | $sed -e "$expr" > $source
rm $tempfile
$ sh expr.sh test.txt
: test.txt
에서 "dog", "cat" 또는 "lion" 을 "tiger"로 치환
역참조
정규 표현식으로 찾은 문자열을 부분적으로 재사용하는 방법이다. 치환 전 문자열의 일부분이 치환 후에 다시 필요한 경우 이용한다.
applicant.csv
의 내용이 아래와 같다고 가정하자.
번호,이름,성별,생년월일,합격여부
1,Peter,남,930503,불합격
2,John,남,911110,불합격
3,Tom,남,880818,불합격
4,Julia,여,89201,불합격
5,Steve,남,921207,합격
6,Alice,여,940616,불합격
여기서 불합격자 중 90년대생 전체를 합격시키는 스크립트를 작성할려고 한다.
우선 정규표현식을 이용하여 생년월일이 "9"로 시작하는 패턴을 찾아야 한다. 하지만 여기서 치환해주어야 할 문자열은 정규표현식으로 찾아낸 생년월일이 아니라 그 뒤에 나오는 합격여부이다.
이 때 역참조를 이용하면 쉽게 해결할 수 있다. \1
이 앞에 내온 생년월일 부분을 대체하고 있다.
#!/bin/bash
# back_reference.sh
case "$(uname)" in
Darwin|*BSD) sed="sed -E" ;; # OS X 또는 BSD 환경
*) sed="sed -r" ;; # GNU 환경
esac
expr="s/(9[0-9]{5},)불합격/\1합격/"
source=$1
tempfile="tempfile"
mv $source $tempfile
cat $tempfile | $sed -e "$expr" > $source
rm $tempfile
$ sh back_reference.sh applicant.csv
$ cat applicant.csv
번호,이름,성별,생년월일,합격여부
1,Peter,남,930503,합격
2,John,남,911110,합격
3,Tom,남,880818,불합격
4,Julia,여,89201,불합격
5,Steve,남,921207,합격
6,Alice,여,940616,합격