관리 메뉴

데브로맨스

【 sed 】 본문

>
【 에디터 】/GNU sed

【 sed 】

데브로맨스 2022. 2. 16. 16:26
반응형

목차

     개념

    • 일반적인 대화형 텍스트 편집기와는 반대 개념
    • 파일의 수정이 주 목적
    • 파일을 순방향으로 읽는 동안 연산 수행 ( 반복 수정에 용이 )
    • 텍스트 스트림을 조작하기 위한 전용 명령

     

     배경

    • 완전한 기능을 갖춘 대화형 편집기를 꺼내들지 않고서도 텍스트 파일에 있는 텍스트를 빨리 조작하기를 원함.

     

     기능

    • 데이터 스트림 편집기
      • 편집기가 데이터를 처리하기 전에 미리 제공 받은 일련의 규칙에 따라서 편집
    • 복잡한 패턴을 만들 수 있도록 텍스트 패턴에 정규 표현식 사용 가능

     

     동작

    1. 입력 수단으로부터 한 번에 하나씩 데이터 줄을 읽어 들인다.
    2. 제공된 편집기 명령으로 데이터를 대조
    3. 명령에서 지정된 대로 스트림 데이터를 변경
    4. 표준 출력 ( STDOUT ) 으로 새로운 데이터를 출력
    • 버퍼 관리 ( Hold and Pattern Buffer Operation )
      • ...

     

     장/단점

    【 장점 】

    • 아무리 크기가 큰 파일이라도 메모리를 거의 사용하지 않음.
    • 쉘 스크립트에서 sed 를 많이 사용하는 이유는, 스트림 조작이 필요할 때 간단히 사용하기 좋기 때문이다.

    【 단점 】

    • 한번 입력된 줄이 지나가면 다시 사용할 수 없다.
    • 다른 언어에서처럼 여러 가지 함수를 제공하지 않는다.
      • 제공하는 명령들을 기능적으로 분류해보면 10가지 정도뿐이다.
      • 간단히 덧셈, 뺄셈을 할 수 있는 산술 연산자도 스트림을 조작하는데 사용할 수 있는 함수도 제공하지 않는다.

     

     특징

    • 모든 명령을 하나의 문자로 표시
    • 모든 텍스트 조작을 정규 표현식을 이용
    • 입력되는 모든 데이터는 문자열 ( text string ) 으로만 취급하고 정규 표현식에 의해 처리됨.
    • 처리 단위는 줄 ( line ) 이다.
      • 줄은 마지막 문자가 newline ( \n ) 으로 끝나는 것을 의미
      • 텍스트 스트림을 처리하는 명령들은 기본적으로 줄  단위이다.
      • 처리를 위해 버퍼에 읽어들일 때도 줄 단위이고, 처리할 때도 줄 단위이다.
      • 처리 단위가 줄 ( line ) 이라고 해서 한버넹 하나의 줄만 처리하는 것은 아니다.
        • 실제로는 multiple line 을 처리하는 데 필요한 명령과 버퍼를 제공한다.

     

     문법

    【 문법 】

     sed 【 -option '[from_address [, to_address]][cmd] {[script]...}' 】 【 text file or from_PIPE 】

     option(s)  -e, -f , -n, -i
     from_address  Number ( start line )
     to_address  Number ( end line ), +Number ( offset )
     group  { ... }
     cmd(s)  [ a / c / d / i / N / n / p / r / w [FileName] / s ]
     script(s)   /pattern/[cmd]

     [cmd]/pattern/replacement/

     /pattern/replacement/[cmd]

     [cmd]/pattern/replacement/[cmd]

     { !, .. }/pattern/replacement/{!, .. }

     

    【 옵션 】

     옵션  설명
     -e script  입력을 처리하는 동안 실행 중인 명령에 스크립트에 지정된 명령을 추가
     -f file, --file  입력을 처리하는 동안 실행 중인 명령에 파일에 지정된 명령을 추가
     -n, --equiet   print 명령이나 플래그로 지정된 행들을 제외한 나머지 행들을 표준 출력으로 보내지 않게 한다.
     -i[suffix], --in-place  표준 출력으로 내보내지 않고 입력 파일의 내용 자체를 바꾼다.

     

    【 명령 】

    명령 설명
       

     

     예제 - 명령 줄에서 편집기 명령 정의  

    $ echo "This is a test" | sed 's/test/big_test/'
    $ echo "This is a test" >> data.txt | sed 's/dog/cat/' data.txt

    echo 명령어 수행 결과로 출력된 문자열 데이터를 파이프로 연결된 다른 프로세스에 전달하면 sed 는 입력된 문자열을 버퍼에 저장 후 변경할 문자(열)를 찾아 치환한 후 결과를 표준 출력으로 보낸다. ( 이 예제에서는 결과를 파일에 저장하지 않는다. )

     예제 - 파일에서 편집기 명령 사용

    $ cat script.sed
    s/brown/green/
    s/fox/elephant/
    s/dog/cat/
    $ sed -f script.sed data.txt

    텍스트 형태로 파일에 저장된 명령들을 -f 옵션을 통해 파일에서 한 줄씩 버퍼로 읽어들인 후 검색 대상 파일에 저장된 문자 데이터와 비교하여 문자열 검색 패턴과 일치하는 문자(열)를 찾아 치환한다.

     예제 - 여러 편집 명령 사용

    $ sed -e 's/brown/green; s/dog/cat/' data.txt
    or
    $ sed -e '
    > s/brown/green/
    > s/fox/elephant/
    > s/dog/cat/' data.txt

    한 줄에 하나 이상의 편집 명령을 수행한다. 굳이 여러 개의 명령을 세미콜론으로 구분하여 한 줄에 다 적을 필요없이 보조 프롬프트를 사용하여 보기 편하게 입력할 수 있다. 

     

     플래그

    • 옵션
     옵션  설명
     숫자  몇 번째로 나타나는 패턴을 새로운 텍스트로 바꿈
     g  기존의 텍스트에서 나타나는 모든 패턴을 바꿈
     p  원래  줄의 내용이 출력
     w file  바꾼 결과를 파일에 쓴다.

     

     예제

    $ sed 's/pattern/replacement/2' origin.txt
    
    $ sed 's/pattern/replacement/g' origin.txt
    
    $ sed 's/pattern/replacement/p' origin.txt
    
    $ sed 's/pattern/replacement/w replacement' origin.txt

    첫 번째 예제는, 두 번째로 일치하는 문자열 패턴만 치환한다. 두 번째 예제는 텍스트 파일 내용 전체를 대상으로 문자열 검색 패턴과 일치하는 문자(열) 전부를 치환한다. 세 번째 예제는 ... 네 번째 예제는 바꾼 결과를 지정된 파일에 쓴다. 

     

     구분자

    • 슬래시 ( / ) 는 문자열 구분자로 사용되기 때문에 패턴 텍스트에 나타나는 경우에는 이스케이프를 위한 백슬래시 ( \ ) 를 사용해야 한다. 이러다 보면 혼란과 실수가 벌어진다. 이 문제를 해결하기 위해 sed 편집기는 바꾸기 명령에서 구분자를 다른 문자로 선택할 수 있다.

     예제

    $ sed 's\/bin\/bash/\/bin\/bash' /etc/passwd
    
    $ sed 's!/bin/bash!/bin/bash!' /etc/passwd

    첫 번째 예제는, 딱 봐도 혼란스럽고 실수를 범하기 쉽다. 두 번째 예제는, 훨씬 쉽게 읽고 이해하기 쉽다. 

     

     주소 사용하기

    • 특정 줄 또는 줄의 그룹에만 명령을 적용하고 싶을 때는 줄의 주소를 사용하면 된다.

     

     예제 - 숫자로 줄 하나 지정 및 범위로 여러 줄 지정

    $ sed '2s/dog/cat/' data.txt
    
    $ sed '2,3s/dog/cat/' data.txt
    
    $ sed '2,$s/dog/cat/' data.txt

    첫 번째 예제는, 두 번째 줄의 문자열에만 명령을 수행할 것을 지정한다. 두 번째 예제는, 두 번째 줄부터 세 번째 줄까지만 명령을 수행할 것을 지정한다. 세 번째 예제는, 두 번째 줄부터 마지막 줄까지 각 줄에 대해 명령을 수행한다. 

     

     예제 - 텍스트 패턴 필터를 사용하여 특정 줄을 걸러내기

    $ sed '/guest/s/bash/csh/' /etc/passwd

    passwd 파일의 내용 중에 guest 문자열이 포함된 줄을 제외하고 검색 대상 파일에서  문자열 검색 패턴과 일치하는 문자(열)을  찾아 치환한다. 

     

     명령 그룹화

    • 각 줄마다 하나 이상의 명령을 수행해야 하는 경우 중괄호 { } 로 명령을 그룹화한다.

     

     예제 - 명령 그룹화하기

    $ sed '2{
    > s/fox/elephant/
    > s/dog/cat/
    }' data.txt
    
    $ sed '3,${
    > s/fox/elephant/
    > s/dog/cat/
    }' data.txt

    첫 번째 예제는, 검색 대상 텍스트 파일에서 두 번째 줄의 문자열에 2개의 명령을 수행한다. 두 번째 예제는, 검색 대상 텍스트 파일에서 세 번째 줄부터 마지막 줄까지 각 줄마다 2개의 명령을 수행한다. 

     

     줄 지우기

    • 제공된 줄 주소 체계와 일치하는 모든 텍스트 줄을 지운다.

     

     예제 - 줄 지우기

    $ cat data.txt
    This is line number 1
    This is line number 2
    This is line number 3
    This is line number 4
    
    $ sed 'd' data.txt              // exam 1)
    $ sed '3d' data.txt             // exam 2)
    $ sed '2,3d' data.txt           // exam 3)
    $ sed '3,$d' data.txt           // exam 4)
    $ sed '/number 1/d' data.txt    // exam 5)

    첫 번째 예제는, 검색 대상 텍스트 파일 전체의 각 줄에 대해 삭제 명령을 수행한다. 정확히는 버퍼에 저장된 문자열을 전부 NULL 로 만들기 때문에 아무것도 출력할 것이 없다.  두 번째 예제는, 세 번째 줄에 대해 삭제 명령을 수행한다. 네 번째 예제는, 두 번재 줄부터 세 번재 줄까지 각 줄에 대해 삭제 명령을 수행한다. 네 번째 예제는, 첫 번째 줄에 문자열 검색 패턴과 일치하는 문자(열)이 포함되어 있으면 삭제한다. 이 모든 예제는 버퍼에 저장된 문자열을 대상으로 명령이 수행되기 때문에 원본 파일의 내용은 그대로 유지하고 있다.  

     

    텍스트 삽입 및 첨부

    • 삽입 명령 : 지정된 줄 바로 앞에 새로운 줄 추가
    • 첨부 명령 : 지정된 줄 다음에 새로운 줄 추가

     

     예제 - 텍스트 삽입

    $ echo "Test Line 2" | sed 'i\Test Line 1'
    Test Line 1
    Test Line 2
    
    $ sed '3i\This is an inserted line.' data.txt
    This is line number 1
    This is line number 2
    This is an inserted line.
    This is line number 3
    This is line number 4

    첫 번째 예제는, 파이프를 통해 전달받은 입력 문자열 ( 문자열 데이터 스트림) 앞에 삽입된다. 두 번째 예제는, 검색 대상 텍스트 파일에서 세 번째 줄 앞에 새로운 줄을 추가한다.

     

     예제 - 텍스트 첨부

    $ echo "Test Line 2" | sed 'a\Test Line 1'
    Test Line 2
    Test Line 1
    
    $ sed '3a\This is inserted line.' data.txt
    
    $ sed '$a\This is inserted line.' data.txt
    
    $ sed '1i\
    > This is one line of new text.\
    > This is another line of new text.' data.txt
    This is one line of new text.
    This is another line of new text.
    This is line number 1
    This is line number 2
    This is line number 3
    This is line number 4
    This is an inserted line.

    첫 번째 예제는, 파이프를 통해 전달받은 입력 문자열 ( 문자열 데이터 스트림 ) 그 다음 줄에 새로운 문자열을 추가한다. 두 번째 예제는, 검색 대상 텍스트 파일에서 세 번째 줄 뒤 ( 네 번째 줄 ) 에 새로운 줄을 추가한다. 세 번재 예제는, 검색 대상 텍스트 파일에서 읽어들이는 문자열 데이터 스트림 끝에 새로운 줄을 덧붙인다. 

     

    줄 바꾸기

    • 변경 ( change ) 명령은 선택된 줄을 새 텍스트로 수정한다는 점을 제외하고는 append 나 insert 와 비슷하다.
    • 주소 범위를 지정하면 change 는 해당 범위의 줄들에서 새 텍스트가 한  번만 나오게 치환한다.

     

     예제 - 줄 바꾸기

    $ cat data.txt
    This is line number 1
    This is line number 2
    This is line number 3
    This is line number 4
    
    $ sed '3c\                                  // example 1)
    > This is chaned line of test' data.txt
    This is line number 1
    This is line number 2
    This is chaned line of test
    This is line number 4
    
    $ sed '/number 3/c\                         // example 2)
    > This is changed line of test' data.txt
    This is line number 1
    This is line number 2
    This is chaned line of test
    This is line number 4
    
    $ sed '2,3c\                                // example 3)
    > This is changed line of test' data.txt
    This is line number 1
    This is chaned line of test
    This is line number 4

    첫 번째 예제는, 검색 대상 텍스트 파일로부터 입력받은 문자열 데이터 스트림의 세 번째 줄의 문자열을 새 문자열로 치환한다.  두 번째 예제는, 세 번째 줄의 문자열이 문자열 검색 패턴과 일치하는 문자(열)을 포함하고 있으면 그 줄을 새로운 문자열로 치환한다. 세 번째 예제는, 두 번째 줄부터 세 번째 줄까지의 전체 문자열을 새로운 문자열로 치환한다. 

     

    문자 변환

    • 변환 ( transform ) 명령 ( y ) 은 한 개의 문자에 대해 실행되는 유일한 명령이다.
    • 변환 명령은 pattern ( 문자열 검색 패턴 ) 와 replacement ( 치환 문자 ) 값을 일대일로 대응시킨다.
    • 변환 명령은 전역 명령이다.
      • 어디에서 나타나든 관계없이 텍스트 줄에서 발견되는 모든 문자에 대해 변환을 수행한다.

    【 파일에 쓰기 】

     [address]y/inchars/outchars

     

     예제 - 한 개의 문자 변환

    $ sed 'y/123/789/' data.txt
    This is line number 7
    This is line number 8
    This is line number 9
    This is line number 4
    This is line number 7 again.
    This is yet another line.
    This is the last line inthe file.

    이 예제는, 텍스트 파일 'data.txt' 에서 입력 받은 문자열 데이터 스트림에서 문자열 검색 패턴에서 각 문자 요소는 1은 7로, 2는 8로 3은 9로 치환하도록 명령을 수행한다.

     

     출력 다시 살펴보기

    • 데이터 스트림의 정보를 출력할 수 있는 세 가지 명령을 알아보자
      • p 명령 : 텍스트 줄을 출력
      • 등호 ( = ) 명령 : 줄 번호를 출력
      • l ( 소문자 L ) 명령 : 줄의 내용을 모두 출력
        • 출력할 수 없는 문자는 백슬래시 ( \ ) 앞에 놓은 8진수 값을 표시하거나,
        • 탭문자 ( \t ) 를 \t 로 표시하는 것처럼 표준 C 스타일의 기호로 표시한다.
        • escape 문자를 포함한 문자열 데이터 스트림이 있다면 목록 명령은 필요한 경우 8진수 코드를 사용하여 이를 표시한다.

     

     예제 -  줄 출력 (1)

    $ echo "this is a test" | sed 'p'
    this is a test
    this is a test
    
    $ cat data.txt
    This is line number 1
    This is line number 2
    This is line number 3
    This is line number 4
    $sed -n '/number 3/p' data.txt    // exam 1)
    
    $ sed -n '2,3p' data.txt          // exam 2)
    This is line number 2
    This is line number 3
    
    $ sed -n '/3/{                    // exam 3)
    > p
    > s/line/test/p
    >}' data.txt
    This is line number 3
    This is test number 3

    첫 번째 예제는, 텍스트 파일 'data.txt' 로부터 입력 받은 문자열 데이터 스트림에서 문자열 검색 패턴을 포함하는 줄의 문자열 ( 인쇄 가능한 ) 을 표준 출력을 통해 모니터로 출력한다. 두 번째 예제는, 2 ~ 3번째 줄의 문자열만 출력한다. 세 번째 예제는, 3번째 줄의 문자열을 먼저 출력한 후 문자열 검색 패턴과 일치하는 문자열을 찾아 치환 후 결과를 출력한다.

     

     예제 - 줄 번호 출력 (2)

    $ cat data.txt
    The qick brown fox jumps over the lazy dog.
    The qick brown fox jumps over the lazy dog.
    The qick brown fox jumps over the lazy dog.
    The qick brown fox jumps over the lazy dog.
    $ sed '=' data.txt
    1
    The qick brown fox jumps over the lazy dog.
    2
    The qick brown fox jumps over the lazy dog.
    3
    The qick brown fox jumps over the lazy dog.
    4
    The qick brown fox jumps over the lazy dog.

    등호 ( = ) 명령은 공백 문자로 구분된 문자열 데이터 스트림에 대해 현재 줄 번호를 출력한다.

     

     예제 - 줄 전체 출력 (3)

    $ cat data.txt
    This	line	contains	tabs.
    $ sed -n 'l' data.txt                         // exam 2)
    This\tline\tcontains\ttabs.$
    
    $cat data.txt
    This line contains an escape character.
    $ sed -n 'l'  data.txt                        // exam 1)
    This line contains an escape character. \a$

    첫 번째 예제는, 줄에 tab 문자를 표준 C 스타일의 기호인 \t 로 표시하여 출력한다. 두 번째 예제는, '삑' 소리를 만들어 내는 escape 제어 문자 코드를 표준 C 스타일의 기호인 \a 로 표시하여 출력한다.

     

     sed 에 파일 사용하기

    • 바꾸기 명령에는 파일 작업을 할 수 있도록 플래그가 포함되어 있지만,
      • 바꾸기 명령을 쓰지 않고도 이런 작업을 할  수 있다.

    【 파일에 쓰기 】

     [address]w filename

     

     예제 - 파일에 쓰기

    $ sed '1,2w test.txt' data.txt
    THis is line number 1
    THis is line number 2
    THis is line number 3
    THis is line number 4
    $
    $ cat test.txt                                     // exam 1)
    THis is line number 1
    THis is line number 2
    
    $cat data.txt
    Blum, R         Browncoat
    McGuiness, A    Alliance
    Bresnahan, C    Browncoat
    Harken, C       Alliance
    $
    $ sed -n '/Browncoat/w Browncoats.txt' data.txt    // exam 2)
    $ cat Browncoats.txt

    첫 번째 예제는, 텍스트 파일 'test.txt' 내용 중 1 ~ 2 줄의 문자열을 'data.txt' 파일에 쓴다. 두 번째 예제는, data.txt 파일 내용 중 'Browncoat' 단어를 포함하는 줄의 인쇄 가능한 모든 문자를 Browncoat.txt 파일에 쓴다.

     

    【 파일로부터 읽기 】

    • 읽기 명령에서는 주소의 범위를 사용할 수 없다.
    • 하나의 줄 번호 또는 텍스트 패턴 주소만을 지정할 수 있다.
     [address]r filename


     예제 - 파일로부터 데이터 읽기

    $ cat data1.txt
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is line number 4.
    $ cat datar2.txt
    This is an added line.
    This is the second added line.
    $
    $ sed '3r data2.txt' data1.txt                // exam 1)
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is an added line.
    This is the second added line.
    This is line number 4.
    $
    $ sed '/number 2/r data2.txt' data1.txt       // exam 2)
    This is line number 1
    This is line number 2
    This is an added line.
    This is the second added line.
    This is line number 3
    This is line number 4
    $
    $ sed '$r data2.txt' data1.txt                // exam 3)
    This is line number 1
    This is line number 2
    This is line number 3
    This is line number 4
    This is an added line.
    This is the second added line.
    
    $ cat data1.txt
    Blum, R         Browncoat
    McGuiness, A    Alliance
    Bresnahan, C    Browncoat
    Harken, C       Alliance
    $
    $ cat notice.std
    Would the following people:
    LIST
    please report to the ship's captain
    $
    $ sed '/LIST/ {                               // exam 4)
    > r data1.txt
    > d
    }' notice.std

    첫 번째 예제는, 텍스트 파일 'data1.txt' 내용 중 3번째 줄 ( 공백 문자로 분리된 3번째 문자열 ) 바로 뒤에 'data2.txt' 의 모든 내용 ( 문자열 데이터 ) 을 삽입한다. 두 번째 예제는, 텍스트 파일 'data1.txt' 내용 중 문자열 검색 패턴과 일치하는 줄 바로 뒤에 'data2.txt' 의 모든 줄을 삽입한다. 세 번째 예제는, 텍스트 파일 'data1.txt' 로 부터 읽은 문자열 데이터 스트림의 끝 ( 마지막 줄 ) 에 'data2.txt' 의 모든 내용을 추가한다. 」  

     

     고급

    멀티라인 명령

    대기 명령

    흐름 바꾸기

    패턴으로 바꾸기

    스크립트에 sed 명령 넣기

     

    반응형
    Comments