본문 바로가기

Learning/└◆Shell Scripts

[Shell Scripting] 유닉스 명령어(2) sed CMD

 

2

sed 명령어(Streamlined Editor) <= 파일을 편집할 수 있다.

 

) --> 

) --> 

) -->  

) --> 

) --> 

) --> 

sed 명령어는 스트림 에디터이다. 역할은 원본 파일에 변형을 주지 않고 단지 출력되는 결과를 변화시켜 보여주는 역할을 한다. 에디터의 일종이기 때문에 vi 편집기와 같은 많은 기능을 제공하고 있다. 또한 sed 명령어는 스크립트 형태로 파일에 저장할 수 있기 때문에 다중 편집이나 쉘 명령행에서 인용부호를 사용하는데 따르는 어려움을 줄여준다. sed 명령어는 쉘스크립트를 사용하여 파일을 편집하는 경우에 많이 사용된다.

) --> 



sed 편집기는 파일을 라인 단위로 읽어 들여서 패턴 스페이스라는 임시퍼버에 놓는다. 그리고 수정하여 기본 출력으로 출력한다. 홀딩 스페이스는 확장적인 연산에 사용된다. 복사, 추가, 비교, 검색 명령어를 사용할 때 이용한다.

 

 

) --> 

(명령어 형식)

# sed [OPTION] 'SCRIPT' filename

) --> 

SCRIPT is

address(s)

command [arguments]

address(s) command [arguments]

) --> 

) --> 

) --> 

(1) 주소 지정(address)

) --> 

주소를 지정(addressing)하면 편집하고자 하는 행을 선택할 수 있다. 주소는 숫자나 정규 표현식, 혹은 둘의 조합으로 표현한다. 특별히 주소를 지정하지 않는 경우 sed 편집기는 입력 파일의 전체 행에 대하여 작업을 진행한다.

) --> 

행번호를 나타내는 숫자가 주소로 사용되면 달러 기호($)는 입력파일의 맨 마지막 행이 진행된다. 두 행 번호를 쉼표(,)로 구분해주면, 두 번호 사이의 숫자나 정규표현식을 써서 혹은 둘의 조합으로 나타낼수 있다.

) --> 

# sed '1,3p' /etc/passwd /* 1 ~ 3 라인 한번더 출력 */ 모니터 상에만

# sed -n '/[Rr]oot/p' /etc/passwd /* Root,root 단어가 검색된 라인만 출력 */

         = grep '[Rr]oot' /etc/passwd

# sed -n '1,/adm/p' /etc/passwd /* root 검색된 라인부터 adm 검색된 라인까지 출력 */

# netstat -an | sed -n '/TCP: IPv4/,/TCP: IPv6/p'


(2). sed 명령어의 command

sed 명령어는 지정된 입력 행들에 대해 수행할 작업을 결정한다. 주소 지정을 생략하면 sed는 입력으로 들어오는 모든 행을 처리한다.

) --> 

 

명령어

설 명

a

현재 행에 하나 이상의 새로운 행을 추가한다.

c

현재 행의 내용을 새로운 내용으로 교체한다.

d

행을 삭제한다.(delete)

i

현재 행의 위에 텍스트를 삽입한다.

h

패턴 스페이스의 내용을 홀드 스페이스에 복사한다.

H

패턴 스페이스의 내용을 홀드 스페이스에 추가한다.

g

홀드 스페이스의 내용을 패턴 스페이스에 복사한다.

패턴 스페이스가 비어있지 않은 경우에는 현재 내용에 덮어쓴다.

G

홀드 스페이스의 내용을 패턴 스페이스에 복사한다.

패턴 스페이스가 비어있지 않은 경우에는 현재 내용에 추가한다.

l

출력되지 않는 특수문자를 명확하게 출력한다.

p

행을 출력한다.(print)

n

다음 입력 행을 첫 번째 명령어가 아닌 다음 명령어에서 처리하게 된다.

q

sed를 종료한다.

r

파일로부터 행을 읽어온다.

!

선택된 행을 제외한 나머지 전체 행에 명령어를 적용한다.

s

문자열을 치환한다.(substitution)

 

) --> 

) --> 

) --> 

[EX1] p command (-p: print)

/etc/passwd 파일에 1번째 라인부터 3번째 라인까지 한번더 출력한다.

) --> 

# sed '1,3p' /etc/passwd

 

root:x:0:0:Super-User:/:/bin/ksh

root:x:0:0:Super-User:/:/bin/ksh

daemon:x:1:1::/:

daemon:x:1:1::/:

bin:x:2:2::/usr/bin:

bin:x:2:2::/usr/bin:

sys:x:3:3::/:

adm:x:4:4:Admin:/var/adm:

lp:x:71:8:Line Printer Admin:/usr/spool/lp:

..... (중략) .....

 

) --> 

) --> 

다음은 /etc/passwd 파일에서 1번째 라인에서 3번째 라인까지만 출력한다.

) --> 

# sed -n '1,3p' /etc/passwd

 

root:x:0:0:Super-User:/:/bin/ksh

daemon:x:1:1::/:

bin:x:2:2::/usr/bin:

 

) --> 

) --> 

다른 활용 방법은 다음과 같다.

# sed -n '/root/p' /etc/passwd /* passwd 파일에서 root 단어가 검색된 라인 출력 */

# sed -n '1,3p' /etc/passwd /* passwd 파일에서 1~3번째 라인 출력 */

# sed -n '10,$p' /etc/passwd /* 10번째 라인부터 마지막 라인까지 출력 */

# sed -n '3p' /etc/passwd /* 3번째 라인만 출력 */

          

[EX2] d command (-d : delete)

/etc/passwd 파일에서 1번째 라인부터 3번째 라인만 제외한 나머지 부분만을 출력한다.

) --> 

# sed '1,3d' /etc/passwd  <= 1~3번을 삭제하기 때문에 1~3번째줄이 보이지 않는다. 모니터상에서만!!!!!!!!!!!!

 

sys:x:3:3::/:

adm:x:4:4:Admin:/var/adm:

lp:x:71:8:Line Printer Admin:/usr/spool/lp:

uucp:x:5:5:uucp Admin:/usr/lib/uucp:

nuucp:x:9:9:uucp Admin:/var/spool/uucppublic:/usr/lib/uucp/uucico

smmsp:x:25:25:SendMail Message Submission Program:/:

listen:x:37:4:Network Admin:/usr/net/nls:

gdm:x:50:50:GDM Reserved UID:/:

webservd:x:80:80:WebServer Reserved UID:/:

postgres:x:90:90:PostgreSQL Reserved UID:/:/usr/bin/pfksh

svctag:x:95:12:Service Tag UID:/:

nobody:x:60001:60001:NFS Anonymous Access User:/:

noaccess:x:60002:60002:No Access User:/:

nobody4:x:65534:65534:SunOS 4.x NFS Anonymous Access User:/:

 

) --> 

) --> 

다른 활용 방법은 다음과 같다.

# sed '3d' /etc/passwd /* 3번째 라인만 삭제하고 출력 */ ='3,3d'

# sed '1,3d' /etc/passwd /* 1~3번째 라인 삭제하고 출력 */

# sed '3,$d' /etc/passwd /* 3번째 라인부터 마지막 라인까지 삭제하고 출력 */

# sed '$d' /etc/passwd /* 마지막 라인을 삭제하고 출력 */

# sed '/root/d' /etc/passwd /* root 스트링이 포함된 라인만 삭제하고 출력 */

         = grep -v 'root' /etc/passwd

) --> 

) --> 

) --> 

[EX3] s command (-s : subtract)

/etc/group 파일에서 root 라는 단어를 찾아서 ROOT로 변경시켜 준다.

) --> 

# sed 's/root/ROOT/' /etc/group

 

ROOT::0:

other::1:ROOT

bin::2:ROOT,daemon

sys::3:ROOT,bin,adm

adm::4:ROOT,daemon

uucp::5:ROOT

mail::6:ROOT

tty::7:ROOT,adm

lp::8:ROOT,adm

nuucp::9:ROOT

staff::10:

daemon::12:ROOT

sysadmin::14:

smmsp::25:

gdm::50:

webservd::80:

postgres::90:

nobody::60001:

noaccess::60002:

nogroup::65534:

 

) --> 

) --> 

) --> 

다음은 /etc/group 파일에서 1번째 라인부터 3번째 라인에 존재하는 root를 찾아서 ROOT로 바꾸어 주는 예이다.

 

g(global)로 한개 라인에 여러개 root가 있을 수 있는데 g가 빠지면

첫번째 만나는 것만 바꿔주고 g를 붙혀야 그

줄에 있는 모든 root를 변경시킴

) --> 

# sed '1,3s/root/ROOT/g' /etc/group

 

ROOT::0:

other::1:ROOT

bin::2:ROOT,daemon

sys::3:root,bin,adm

adm::4:root,daemon

uucp::5:root

mail::6:root

tty::7:root,adm

lp::8:root,adm

nuucp::9:root

staff::10:

daemon::12:root

sysadmin::14:

smmsp::25:

gdm::50:

webservd::80:

postgres::90:

nobody::60001:

noaccess::60002:

nogroup::65534:

 

) --> 

 

이것은 꼭 알아두자

다른 활용 방법은 다음과 같다.

# sed 's/root/ROOT/g' /etc/passwd /* root->ROOT 치환 */

# sed 's/^root/ROOT/g' /etc/passwd /* 문서전체에서 라인의 처음 root->ROOT */

# sed -n 's/^root/ROOT/p' /etc/passwd /* 검색된 라인의 처음 root->ROOT */

# sed -n 's/root/ROOT/gp' /etc/passwd /* 검색된 라인의 root->ROOT, Globally, print */

# sed 's/[0-9][0-9]$/&.5/' /etc/passwd /* 라인의 마지막 두개의 숫자뒤에 .5 붙임 */

# sed 's/(Mar)got/1ianne/p' datafile /* Margot -> Marianne */

# sed 's/^....//' filename /* 각행의 첫 4글자 삭제 */

# sed 's/....$//' filename /* 각행의 마지막 4글자 삭제 */

# sed 's#/test/file.sh#/test/file.c#g' file1 /* /test/file.sh -> /test/file.c */ 복잡하기 때문에 #으로 구분하기 위해

# sed 's;/test/file.sh;/test/file.c;g' file1 /* /test/file.sh -> /test/file.c */

) --> 

마지막 경우는 찾을려고하는 문자열안에 ‘/’문자가 들어 있는 경우에는 s/*/*/ 형식을 사용할수 없을것이다. 따라서 다른 문자를 구분자로 사용하여야 한다. 이런경우 ‘#’, ‘?’등 다른 부호들을 사용하면 된다. ‘#’만 쓸수 있는 것은 아니다. 형식에만 맞는다면 다른 부호도 상관이 없다.

) --> 

) --> 

) --> 

[EX4] 행의 선택 범위: 쉼표(,)

/etc/passwd 파일의 root 문자열부터 adm 문자열까지 출력하여 준다.

) --> 

# sed n '/^root/,/^adm/p' /etc/passwd

 

root:x:0:0:Super-User:/:/bin/ksh

daemon:x:1:1::/:

bin:x:2:2::/usr/bin:

sys:x:3:3::/:

adm:x:4:4:Admin:/var/adm:

 

) --> 

) --> 

다음 예제는 5번째 라인부터 라인의 처음이 nobody로 시작하는 라인까지 출력하여 준다.

) --> 

# sed -n '5,/^nobody/p' /etc/passwd

 

adm:x:4:4:Admin:/var/adm: <----- 5번째 라인

lp:x:71:8:Line Printer Admin:/usr/spool/lp:

uucp:x:5:5:uucp Admin:/usr/lib/uucp:

nuucp:x:9:9:uucp Admin:/var/spool/uucppublic:/usr/lib/uucp/uucico

smmsp:x:25:25:SendMail Message Submission Program:/:

listen:x:37:4:Network Admin:/usr/net/nls:

gdm:x:50:50:GDM Reserved UID:/:

webservd:x:80:80:WebServer Reserved UID:/:

postgres:x:90:90:PostgreSQL Reserved UID:/:/usr/bin/pfksh

svctag:x:95:12:Service Tag UID:/:

nobody:x:60001:60001:NFS Anonymous Access User:/:

 

) --> 

) --> 

다른 활용 방법은 다음과 같다.

# sed '/export/s/-/rq/g' /etc/vfstab /* vfstab 파일에서 export가 존재하는 라인을 검

색하고 그 라인의 '-''rq'로 변경한다. */

# sed '/west/,/east/s/$/**VACA**/' datafile /* west가 존재하는 라인부터 esat가 존재하는 라

인까지 검색하고 라인의 마지막에 '**VACA**'

붙인다. */

# sed '1,15s/$/**VACA**/' datafile /* 1번째 라인부터 15번째 라인까지 라인의 마지막에

'**VACA**'를 붙인다. */

) --> 

[EX] /etc/vfstab 파일 편집

# sed 's/data1/data2/' fstab

data1이란걸 검색하여 data2로 변경한다.


 

 

sed동작원리


sed명령어를 사용하면 모니터에만 출력해주는 것이다.

이것을 임시적으로 tmp파일에 저장하고 tmp파일을 원본파일에 Overwrite하는 것이다.

파일을 열고 있기 때문에 Overwrite가 안되서 바로하는 것이 불가능하기 때문에 이렇게 사용하는 것이다.



sed -i 's/data1/data2/ fstab

=> i옵션을 사용하면바로 overwrite된다 (내부적으론 tmp파일을 생성하여 원본에 overwrite하는 것이다)




# sed '/export/s/-/rq/' /etc/vfstab > /tmp/vfstab.orig

# cp /tmp/vfstab.orig /etc/vfstab

) --> 

(3). sed 명령어 옵션

) --> 

 

옵션

설 명

-e

다중 편집을 가능하게 한다.

-f

sed 스크립트 파일 지정에 사용된다.

-n

기본 출력을 생략한다.

 

) --> 

) --> 

) --> 

[EX1] -n 옵션 (-n : not default)

/etc/passwd 파일의 1번째 라인부터 3번째 라인까지 출력한다.

) --> 

# sed -n '1,3p' /etc/passwd

 

root:x:0:0:Super-User:/:/bin/ksh

daemon:x:1:1::/:

bin:x:2:2::/usr/bin:

 

) --> 

) --> 

) --> 

[EX2] -e 옵션 (-e : extended)

/etc/passwd 파일중 1번째 라인부터 3번째 라인까지 삭제하고 나머지 부분에 관해서 no을 찾아 NO로 치환한다.

) --> 

# sed -e '1,5d' -e 's/no/NO/g' /etc/passwd (# sed -e '1,5d' /etc/passwd | sed -e 's/no/NO/g')

 

lp:x:71:8:Line Printer Admin:/usr/spool/lp:

uucp:x:5:5:uucp Admin:/usr/lib/uucp:

nuucp:x:9:9:uucp Admin:/var/spool/uucppublic:/usr/lib/uucp/uucico

smmsp:x:25:25:SendMail Message Submission Program:/:

listen:x:37:4:Network Admin:/usr/net/nls:

gdm:x:50:50:GDM Reserved UID:/:

webservd:x:80:80:WebServer Reserved UID:/:

postgres:x:90:90:PostgreSQL Reserved UID:/:/usr/bin/pfksh

svctag:x:95:12:Service Tag UID:/:

NObody:x:60001:60001:NFS ANOnymous Access User:/:

NOaccess:x:60002:60002:No Access User:/:

NObody4:x:65534:65534:SunOS 4.x NFS ANOnymous Access User:/:

 

) --> 

) --> 

) --> 

[EX3] -f Option

스크립트 파일의 내용을 읽어 들여서 sed 명령어를 실행한다. 이 경우는 sed 명령어의 -e 옵션을 통해 다중 옵션이 긴 경우에 적당하다.

) --> 

# cat script.sed

 

1,5d

s/no/NO/g

 

) --> 

# sed -f script.sed /etc/passwd

 

lp:x:71:8:Line Printer Admin:/usr/spool/lp:

uucp:x:5:5:uucp Admin:/usr/lib/uucp:

nuucp:x:9:9:uucp Admin:/var/spool/uucppublic:/usr/lib/uucp/uucico

smmsp:x:25:25:SendMail Message Submission Program:/:

listen:x:37:4:Network Admin:/usr/net/nls:

gdm:x:50:50:GDM Reserved UID:/:

webservd:x:80:80:WebServer Reserved UID:/:

postgres:x:90:90:PostgreSQL Reserved UID:/:/usr/bin/pfksh

svctag:x:95:12:Service Tag UID:/:

NObody:x:60001:60001:NFS ANOnymous Access User:/:

NOaccess:x:60002:60002:No Access User:/:

NObody4:x:65534:65534:SunOS 4.x NFS ANOnymous Access User:/:

 

(4). 메타문자(Metacharacter)

) --> 

grep 명령어와 마찬가지로 sed 명령어도 패턴 검색을 위하여 다수의 특별한 메타문자를 제공한다. 기존의 grep 명령어에서 제공하는 모든 메타 문자의 가능이 가능하며 추가적인 문자도 존재한다. 다음은 추가적인 메타문자의 사용 설명이다.

) --> 

 

메타문자

기능

사용예

사용 예 설명

&

검색열을 저장하여 치환열에서 사용할 수 있게 한다.

s/love/**&**/

앰퍼샌드(&)는 검색열을 나타낸다. 문자열 love가 앰퍼샌드로 치환된다. 왼쪽의 경우 love**love**로 치환된다.

 

) --> 

) --> 

[EX1] 추가적인 메타문자 확인 예

# cat datafile

 

northwest NW 3 23

western WE 4 11

southwest SW 5 9

northeast NE 6 18

north NO 7 15

central CT 8 5

 

) --> 

# sed 's/[0-9][0-9]$/&.5/' datafile /* 라인의 마지막 두숫자에 .5 붙이기 */

 

northwest NW 3 23.5

western WE 4 11.5

southwest SW 5 9

northeast NE 6 18.5

north NO 7 15.5

central CT 8 5

 

) --> 

) --> 

) --> 

꼭 알아두자


 

[참고] 스크립트에서 sed 명령어를 통한 파일 편집

일반적으로 스크립트안에서 파일 편집할수 있도록 설정할려면, sed 명령어를 통해 가능하다.

) --> 

다음 예제는 /etc/default/login 파일을 편집한 예이다.

(편집) CONSOLE=/dev/console -> #CONSOLE=/dev/console

=> root 사용자로 telnet 할수 있도록 설정

# sed 's?^CONSOLE?#CONSOLE?' /etc/default/login > /tmp/.tmp1

# mv /tmp/.tmp1 /etc/default/login

) --> 

== sed -i

) --> 

다음은 /etc/ftpd/ftpusers 파일을 편집한 예이다.

(편집) root 사용자 이름 삭제

=> root 사용자로 ftp 할수 있도록 설정

) --> 

# sed '/^root/d' /etc/ftpd/ftpusers > /tmp/.tmp2 (# grep -v '^root' /etc/ftpd/ftpusers)

# mv /tmp/.tmp2 /etc/ftpd/ftpusers

 

) --> 

 

[참고] sed 명령어에서 변수를 사용하기 위해서

) --> 

sed 명령어에서 찾을려고하는 패턴을 지정하는 경우 쉘스크립트 안에서 사용하는 경우, 찾을려고 하는 패턴 부분에 변수를 지정해야 하는 경우가 있다면, 작은 따옴표('')를 사용하지 말고 큰 따옴표("")를 사용해야 한다.

) --> 

# cat sed.sh

---------------------------------------------------------------------

#!/bin/ksh

) --> 

PATTERN=root

sed "/^$PATTERN/d" /etc/passwd

) --> 

..... (중략) .....

---------------------------------------------------------------------

) --> 

 

 

[참고] 주석처리 구문에 대해서

) --> 

# cat /etc/defaultrouter /* 주석처리가 허용되지 않는 파일 */

 

172.16.0.1

 

) --> 

# cat /etc/hosts /* 주석처리가 허용되는 파일 */

 

#

# Internet host table

#

::1 localhost

127.0.0.1 localhost

172.16.9.249 solaris249 solaris249.example.com loghost

192.168.10.249 nic3

 

) --> 

) --> 

/etc/defaultrouter 파일을 읽어 들여서 defaultrouter 설정하는 부팅 스크립트

# cat defaultrouter.sh

---------------------------------------------------------------------

#!/bin/ksh

<---- /etc/defaultrouter 파일의 주석 처리 구문 X

DEFAULT_ROUTER=`cat /etc/defaultrouter`

route add default $DEFAULT_ROUTER

) --> 

---------------------------------------------------------------------

) --> 

/etc/hosts 파일을 읽어 들어서 부팅시에 IP 설정하는 스크립트

# cat ip.sh

---------------------------------------------------------------------

.....

grep v '^#' /etc/hosts > /tmp/.tmp1 <---- /etc/hosts 파일의 주석 처리 구문 0

) --> 

IP=`cat /etc/hostname.e1000g0`

ifconfig e1000g0 $IP ......

) --> 

---------------------------------------------------------------------

) --> 

 

) --> 

) -->