Tips
sed 명령을 변수에 저장해 실행하기
$ AA="s/^/X/" BB='s/$/Y/'
$ echo 12345 | sed "$AA; $BB"
X12345Y
$ CC="i-------"
$ echo 12345 | sed "$CC; $AA; $BB" # i, a, c 명령은
-------; s/^/X/; s/$/Y/
12345
$ echo 12345 | sed -e "$CC" -e "$AA; $BB" # -e 옵션을 사용해 분리해야 한다.
-------
X12345Y
pattern space 에 라인을 insert, append 하기
i
, a
명령은 pattern space 에는 라인이 추가되지 않습니다.
pattern space 의 특정 위치에 라인을 insert, append 하려면 다음과 같은 방법을 이용합니다.
# 3 번째 라인 앞에 추가
# ":X $!{N; bX};" 는 전체 라인을 pattern space 로 읽어 들입니다.
$ echo -e "111\n222\n333\n444" | sed -E ':X $!{N; bX}; s/^/XXXXX\n/M3'
111
222
XXXXX
333
444
# 3 번째 라인 뒤에 추가
$ echo -e "111\n222\n333\n444" | sed -E ':X $!{N; bX}; s/$/\nXXXXX/M3'
111
222
333
XXXXX
444
# 처음 라인 앞에 추가
$ echo -e "111\n222\n333" | sed -E ':X $!{N; bX}; s/^/XXXXX\n/'
XXXXX
111
222
333
# 마지막 라인 뒤에 추가
$ echo -e "111\n222\n333" | sed -E ':X $!{N; bX}; s/$/\nXXXXX/'
111
222
333
XXXXX
-i
옵션 사용시 터미널로 출력하기
-i
옵션을 이용해 파일을 수정할 경우 출력이 파일로 저장되기 때문에
터미널에는 아무런 메시지가 표시되지 않는데요.
다음과 같이 하면 필요할 경우 stderr 로 출력할 수 있습니다.
# bar 가 zoo 로 치환될 경우 file 로 결과가 저장되는 동시에 stderr 로도 출력이 된다.
$ sed -i -e '/foo/{ s/bar/zoo/w /dev/stderr' -e '}' file
데이터를 보는 안목을 기르자
다음과 같이 숫자가 섞여있는 라인에서 N 번째 숫자를 추출하려고 합니다.
이와 같은 경우 먼저 숫자가 아닌 문자들을 삭제해버리면 이후에 추출하기가 수월해집니다.
# 세 번째 숫자에 해당하는 13963 추출하기
[ 2014/05/01 10:48:26 | 13963 | DEBUG ] It took 11.16837501525879 seconds to complete
$ sed -E 's#[^0-9./:]# #g' file
2014/05/01 10:48:26 13963 11.16837501525879
$ sed -E 's#[^0-9./:]# #g; s/\s*(\S+\s+){2}(\S+).*/\2/' file
13963
# 또는
$ sed -E 's/([^0-9]*([0-9]+)){7}.*/\2/' file
13963
다음 예는 0 보다 큰 숫자들을 전부 1 로 변경하려고 하는데요.
이때는 각 컬럼 값을 0 보다 큰지 일일이 비교할 필요 없이 regex 를 이용해 해결할 수 있습니다.
# 데이터 내용
a b c
A 5 2 0
B 0 3 4
C 7 3 4
D 2 0 2
# 두 자리 이상의 숫자도 포할될 경우는 's/[0-9]{2,}|[1-9]/1/g'
$ sed 's/[1-9]/1/g' file
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1
스크립트가 길때 개행하는 방법
스크립트 명령은 -e
옵션으로 구분하여 실행 할 수 있습니다.
$ sed -e 's/hamster/this is a hamster./' \
-e 's/parrot/this is a parror./' \
-e 's/turtle/this is a turtle./' file
-e
옵션은 명령 단위로 분리해 작성해야 하므로
만약에 s
하나의 명령이 길어질 경우는 위 방법으로는 안되고
다음과 같이 backslash-newline 을 사용해야 합니다.
$ sed -Ez 's#(\s*)<servlet-name>(\s+)cofaxTools(\s+)</servlet-name>#'\
'\1<servlet-class>\2org.cofax.cms.CofaxToolsServlet\3</servlet-class>#' file
$ sed -En '/(([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}'\
'([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])/p' <<\@
192.168.0.1
127.0.0.1
123.456.789.101
10.1.2.4
@
192.168.0.1
127.0.0.1
10.1.2.4
sed 보다 다른 명령을 사용하는게 효율적일 경우
특정 스트링을 추출하거나 N 번째 필드를 추출할 때는 sed 보다는 grep, awk 명령을 이용하는 것이 효율적입니다.
$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 7.8G 0 7.8G 0% /dev
tmpfs 1.6G 1.7M 1.6G 1% /run
/dev/sda5 28G 13G 14G 49% /
tmpfs 7.8G 67M 7.8G 1% /dev/shm
# "숫자%" 로 구성된 항목을 추출
$ df -h | sed -E 's/([0-9]+%)|./\1/g'
0%
1%
49%
1%
# grep 명령을 이용하는 것이 효율적입니다.
$ df -h | grep -Eo '[0-9]+%'
0%
1%
49%
1%
--------------------------------------------
# 4번째 컬럼 값을 추출
$ df -h | sed -E 's/(\S+\s+){3}(\S+).*/\2/'
Avail
7.8G
1.6G
14G
7.8G
# awk 명령을 이용하는 것이 효율적입니다.
$ df -h | awk '{ print $4 }'
Avail
7.8G
1.6G
14G
7.8G