"Sed"의 두 판 사이의 차이
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
이것저것
- 주석과 빈 줄을 지우기
$ sed -e 's/#.*//;/^$/d' thegeekstuff.txt
- dos style CRLF를 unix style로 바꾸기
$sed 's/.$//' filename
- html tag 제거하기
$ sed -e 's/<[^>]*>//g'
- 첫째줄과 마지막줄을 파일에 쓰기
$ sed -n -e '1w output.txt' -e '$w output.txt' thegeekstuff.txt
- 구분자(delimiter)로 '/'대신 '@'를 쓸 수 있다.
- '&'로 앞서 match된 string전체를 얻을 수 있다.
- 각 단어의 첫글자에 괄호치기
$ echo "Welcome To The Geek Stuff" | sed 's/\(\b[A-Z]\)/\(\1\)/g'
- 숫자에 쉼표 넣기
$ 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 - 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 - 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) - file의 total number출력
$ sed -n '$=' thegeekstuff.txt
6 - 두 라인을 하나로 병합.
$ sed -e '{
N
s/\n/ @ /
}' thegeekstuff.txt - non-blank라인의 라인 번호와 그 라인내용 출력 (원문과 다름)
sed -n -e '/./=' -e '/./p' sed-ex.txt | sed 'N;s/\n/ /'
- 연속된 두개의 빈 라인을 지움
$ sed '/^$/{
N
/^\n$/d
}' thegeekstuff.txt - 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
- 마지막 두 라인을 지움
$ sed 'N;$!P;$!D;$d' thegeekstuff.txt
- P : pattern space의 첫줄만 출력한다.(\n으로 구분)
- D : pattern space의 첫줄만 지우고, 다음 cycle을 시작한다.(남은 명령을 실행하지 않는다)
- 마지막 줄에 도달하면 $!P, $!D명령이 실행되지 않음에 유의.
- 파일의 마지막 두줄 출력
$ sed '$!N;$!D' thegeekstuff.txt
- 끝에서 두번째 줄에서는 맨 끝줄과 합해져서 '$'조건을 만족시키고, 따라서 그냥 출력.
- 마지막줄에서는 합해지는 과정도 일어나지 않음.
- 홀수 줄을 가진 파일을 대상으로 sed -n 'N;p;=;' odd-number-file.txt 를 실행시켜보면, 마지막 줄은 출력되지 않음을 볼 수 있다.
pattern space, hold space
(출처)
- 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가 됨.
- 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로 옮긴다
- 마지막까지 반복되고 파일 끝($)에서 출력된다.
- 특정 패턴이 포함된 문단만 출력
$ 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옵션이 없음에 다시 유의)
- 빈 줄이 나올 때까지 모두 hold space로 옮긴다. $!d; d명령은 Delete the pattern space and start the next cycle. 이므로, 이 명령이 없으면 다음 cycle을 시작하기 전 모두 출력되고(sed명령에 -n옵션이 없으므로) hold space는 비워져버린다.
- 특정 패턴이 등장하는 줄의 바로 직전 줄을 출력하기
$ sed -n '/Mysql/{g;1!p;};h' thegeekstuff.txt
- 모든 줄에 대해 hold space로 옮기는 h명령이 적용된다
- 만일 패턴(이 명령에서는 Mysql)이 일치하면, hold space에 있던 라인(직전 라인)을 가져와서 출력.
- 만일 첫번째 줄에서 일치하는 것이 나온다면, hold space는 비어 있을 것이므로 그 라인을 출력하지 않기 위해 p가 아니라 1!p를 줌. sed가 각 라인별로 실행되지만 현재 라인수를 기억하고 있음을 주시할 것.
- 각 문단의 마지막줄을 삭제하기
$ 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명령 실행으로 삭제된다.
- 각 줄 끝에 직전 줄을 붙이기
$ sed 'H;x;s/^\(.*\)\n\(.*\)/\2\1/' thegeekstuff.txt
- 모든 줄의 처음부분에 특정 단어를 넣되, 단락별로 다르게. 각 단락은 '#'으로 시작하는 특정 단어(=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'
숫자만 뽑아내기
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