"Sed"의 두 판 사이의 차이

ph
이동: 둘러보기, 검색
 
84번째 줄: 84번째 줄:
 
http://unix.stackexchange.com/questions/56429/how-to-print-all-lines-after-a-match-up-to-the-end-of-the-file
 
http://unix.stackexchange.com/questions/56429/how-to-print-all-lines-after-a-match-up-to-the-end-of-the-file
 
{{break}}
 
{{break}}
 +
 +
==숫자만 뽑아내기==
 +
echo 'lsdfj slfj 23423423 slfjsd flsdf' | sed -e 's/[^0-9]*\([0-9]\+\).*/\1/'
 +
아래와 같이 하면 동작하지 않는다.
 +
echo 'lsdfj slfj 23423423 slfjsd flsdf' | sed -e 's/.*\([0-9]\+\).*/\1/'
 +
앞의 <code>.*</code>가 greedy하기 때문.
 +
<br>grep을 쓰는 것이 가장 편하다.
 +
echo 'lsdfj slfj 23423423 slfjsd flsdf' | grep -oP '\d+'
 +
P는 perl regexp를 쓰겠다는 뜻, o는 print only-maching

2017년 5월 31일 (수) 14:16 기준 최신판

articles

The Geek Stuff의 unix sed tutorial 예제들

주소지정

(출처)

  • 대표유형

    # sed -n 'ADDRESS'p filename
    # sed -n '/PATTERN/p' filename

  • 다음 유형들이 모두 유효하다

    # sed -n ‘N’p filename
    # sed -n ‘M~N’p filename
    # sed -n ‘M,N’p filename
    # sed -n ‘$’p filename
    # sed -n ‘N,$p’ filename

    • 'N'p나 'M,N'p대신 'Np'나 'M,Np'를 써도 된다. 따옴표를 모두 제거하고 Np나 M,Np로 써도 된다. 하지만 'N,$'등과 같이 기호가 들어가면 꼭 따옴표 안에 넣어주어야 한다.
    • BSD버전 sed는 '~'가 듣지 않았다.(mac os x)
    • $를 pattern으로 지정하면 맨 끝 줄에 명령이 적용된다.
  • 다음 유형들도 모두 유효하다

    # sed -n /PATTERN/p filename
    # sed -n ‘/PATTERN/,Np’ filename
    # sed -n ‘N,/PATTERN/p’ filename
    # sed -n ‘/PATTERN/,$p’ filename
    # sed -n ‘/PATTERN/,+Np’ filename
    # sed -n ‘/P1/,/P2/p’ filename

이것저것

  1. 주석과 빈 줄을 지우기

    $ sed -e 's/#.*//;/^$/d' thegeekstuff.txt

  2. dos style CRLF를 unix style로 바꾸기

    $sed 's/.$//' filename

  3. html tag 제거하기

    $ sed -e 's/<[^>]*>//g'

  4. 첫째줄과 마지막줄을 파일에 쓰기

    $ sed -n -e '1w output.txt' -e '$w output.txt' thegeekstuff.txt

  5. 구분자(delimiter)로 '/'대신 '@'를 쓸 수 있다.
  6. '&'로 앞서 match된 string전체를 얻을 수 있다.
  7. 각 단어의 첫글자에 괄호치기

    $ echo "Welcome To The Geek Stuff" | sed 's/\(\b[A-Z]\)/\(\1\)/g'

  8. 숫자에 쉼표 넣기

    $ cat numbers
    1234
    12121
    3434
    123
    $sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers
    1,234
    12,121
    3,434
    123

  9. a(ppend), i(nsert), c(hange) 명령의 사용례

    $ sed '/Sysadmin/a \
    > Linux Scripting' thegeekstuff.txt
    $ sed '$ a\
    > Website Design' thegeekstuff.txt
    $ sed '4 i\
    > Cool gadgets and websites' thegeekstuff.txt
    $ sed '1 c\
    > The Geek Stuff' thegeekstuff.txt
    # file line number 출력
    $ sed -n '/Databases/=' thegeekstuff.txt

    2

  10. line number및 line출력

    $ sed -n '/Oracle/,/Productivity/{
    > =
    > p
    > }' thegeekstuff.txt

    2
    Databases - Oracle, mySQL etc.
    3
    Security (Firewall, Network, Online Security etc)
    4
    Storage in Linux
    5
    Productivity (Too many technologies to explore, not much time available)

  11. file의 total number출력

    $ sed -n '$=' thegeekstuff.txt

    6

  12. 두 라인을 하나로 병합.

    $ sed -e '{
    N
    s/\n/ @ /
    }' thegeekstuff.txt

  13. non-blank라인의 라인 번호와 그 라인내용 출력 (원문과 다름)

    sed -n -e '/./=' -e '/./p' sed-ex.txt | sed 'N;s/\n/ /'

  14. 연속된 두개의 빈 라인을 지움

    $ sed '/^$/{
    N
    /^\n$/d
    }' thegeekstuff.txt

  15. tail의 특정 문자열을 강조해서 보기

    $ tail -f somefile | sed -e "s/https/\x1b[31m&\x1b[0m/g"


http://www.thegeekstuff.com/tag/sed-tips-and-tricks/ multiline file operation. to be continued

  1. 마지막 두 라인을 지움

    $ sed 'N;$!P;$!D;$d' thegeekstuff.txt

    • P : pattern space의 첫줄만 출력한다.(\n으로 구분)
    • D : pattern space의 첫줄만 지우고, 다음 cycle을 시작한다.(남은 명령을 실행하지 않는다)
    • 마지막 줄에 도달하면 $!P, $!D명령이 실행되지 않음에 유의.
  2. 파일의 마지막 두줄 출력

    $ sed '$!N;$!D' thegeekstuff.txt

    • 끝에서 두번째 줄에서는 맨 끝줄과 합해져서 '$'조건을 만족시키고, 따라서 그냥 출력.
    • 마지막줄에서는 합해지는 과정도 일어나지 않음.
      • 홀수 줄을 가진 파일을 대상으로 sed -n 'N;p;=;' odd-number-file.txt 를 실행시켜보면, 마지막 줄은 출력되지 않음을 볼 수 있다.

pattern space, hold space

(출처)

  1. thegeekstuff.txt의 내용을 double space로

    $ sed 'G' thegeekstuff.txt

    • 한 줄 읽어 pattern space로 읽어오면,
    • G명령으로 hold space에 있는 것이 가서 붙음.(Append a newline character followed by the contents of the hold space to the pattern space.이므로 hold space가 비었다면 빈 줄이 붙는다)
    • 같은 방식으로 'G;G'하면 triple space가 됨.
  2. thegeekstuff.txt를 줄(line)단위로 역순 출력.

    $ sed -n '1!G;h;$p' thegeekstuff.txt

    • 한줄을 읽어온 뒤 그대로 hold space로 저장한다
    • 그 줄을 제외하고(2줄부터) G;h 가 반복되는데,
    • G명령으로 hold space에 있는 것들이 pattern space에 붙는다. 1줄이 그대로 hold space에 들어 있으므로 (2줄이 pattern space에 들어온 뒤) 1줄이 2줄 뒤에 붙게 된다.
    • 다음 h명령이 pattern space를 hold space로 옮긴다
    • 마지막까지 반복되고 파일 끝($)에서 출력된다.
  3. 특정 패턴이 포함된 문단만 출력

    $ sed -e '/./{H;$!d;}' -e 'x;/Administration/!d' thegeekstuff.txt

    • 빈 줄이 나올 때까지 모두 hold space로 옮긴다. $!d; d명령은 Delete the pattern space and start the next cycle. 이므로, 이 명령이 없으면 다음 cycle을 시작하기 전 모두 출력되고(sed명령에 -n옵션이 없으므로) hold space는 비워져버린다.
      •  ! (exclamation) : Editing commands can be applied to non-selected pattern spaces by use of the exclamation character function.
      • 위 명령에서 .(dot)은 모든 character에 해당하므로 $!d명령은 start the next cycle의 효과만 가지게 된다.
    • 빈 줄이 나오면 hold space와 pattern space를 exchange. 주어진 패턴이 없다면 지운다. 있으면 출력된다.(sed에 -n옵션이 없음에 다시 유의)
  4. 특정 패턴이 등장하는 줄의 바로 직전 줄을 출력하기

    $ sed -n '/Mysql/{g;1!p;};h' thegeekstuff.txt

    • 모든 줄에 대해 hold space로 옮기는 h명령이 적용된다
    • 만일 패턴(이 명령에서는 Mysql)이 일치하면, hold space에 있던 라인(직전 라인)을 가져와서 출력.
    • 만일 첫번째 줄에서 일치하는 것이 나온다면, hold space는 비어 있을 것이므로 그 라인을 출력하지 않기 위해 p가 아니라 1!p를 줌. sed가 각 라인별로 실행되지만 현재 라인수를 기억하고 있음을 주시할 것.
  5. 각 문단의 마지막줄을 삭제하기

    $ sed -n -e '/^$/{x;d;}' -e '/./x;p' thegeekstuff.txt

    • 빈 줄이 아니면 pattern space와 hold space를 exchange하고 출력한다. 첫줄에 hold space는 빈줄이므로 빈 줄이 출력될 것이다. 이를 막기 위해 1!p를 줄 수 있다.
    • 빈 줄이 나왔을 때 {x;d;}가 실행되는데, hold space에는 직전 줄이 들어있으므로, exchange후 d명령 실행으로 삭제된다.
  6. 각 줄 끝에 직전 줄을 붙이기

    $ sed 'H;x;s/^\(.*\)\n\(.*\)/\2\1/' thegeekstuff.txt

  7. 모든 줄의 처음부분에 특정 단어를 넣되, 단락별로 다르게. 각 단락은 '#'으로 시작하는 특정 단어(=tag)를 가짐.(Prepend tag of every block to every line of that block)

    $ sed '
    /^#/{
    h
    d
    }
    G
    s/^\(.*\)\n#\(.*\)/\2 \1/' thegeekstuff.txt

    • '#'으로 시작하는 줄을 만나면 hold space로 옮기고 pattern space를 비운 뒤, (출력하지 않고) 다음 cycle진행.
    • (모든 줄에 대해) hold space에 있는 것을 가져와서 pattern space에 붙이고, 치환명령으로 그 둘의 자리를 바꿈.(tag이 행 처음에 나오도록.)




Nongreedy option

Neither basic nor extended Posix/GNU regex recognizes the non-greedy quantifier;
Use perl.

$ perl -pe 's|(http://.*?/).*|\1|'

http://stackoverflow.com/a/1103177/766330


특정 패턴 이후부터 출력

sed '0,/pattern/d'

http://unix.stackexchange.com/questions/56429/how-to-print-all-lines-after-a-match-up-to-the-end-of-the-file


숫자만 뽑아내기

echo 'lsdfj slfj 23423423 slfjsd flsdf' | sed -e 's/[^0-9]*\([0-9]\+\).*/\1/'

아래와 같이 하면 동작하지 않는다.

echo 'lsdfj slfj 23423423 slfjsd flsdf' | sed -e 's/.*\([0-9]\+\).*/\1/'

앞의 .*가 greedy하기 때문.
grep을 쓰는 것이 가장 편하다.

echo 'lsdfj slfj 23423423 slfjsd flsdf' | grep -oP '\d+'

P는 perl regexp를 쓰겠다는 뜻, o는 print only-maching