Sed

Stream EDiter 의 약자

출처

  • 원본 아래 내용은 개인용으로 정리한 내용 입니다.

s 커맨드

echo day > old
# sed script sourcefile > destfile
sed s/day/night/ old > new

echo day | sed s/day/night/ 
# night

'' 를 쓰는걸 추천

상황에 따라 써도 안써도 되지만 홑따움표를 쓰는걸 추천한다. Detail About Quote

echo day | sed 's/day/night/'
# night

정확이 명시한것만 치환 나머지는 그냥 출력

echo Sunday | sed 's/day/night/'
# Sunnight

Sed는 라인 단위로 동작한다.

  • 특정 신호를 주지 않으면 기본은 맨앞에꺼 한개 치환
test.txt
one two three, one tow three
for three two one
one hundrad

sed 's/one/ONE/' < test.txt

# ONE two three, one two three
# for three two ONE
# ONE hundrad

s 커맨드 문법

문자열에서 특정 패턴을 찾아 그 부분만 변환 문자열로 변환 (없으면 유지)

symbol desc
s 치환 명령어
/../../ 경계기호 delimit (de-'down'm limitara-'limit'')
one 찾을 정규식 패턴
ONE 변환 될 스트링

경계기호 슬래시에 대해서

슬래시를 경계 기호로 쓰기 때문에 패턴 자체에 슬래시가 있으면 이스케이프 문자를 통해 치환 해주어야 한다. "\" 하지만 보기 나쁨으로 다른 경계기호를 사용하기도 한다. "_", ":", "|"

echo /home/a > old
sed 's/\/home\/a/\/newhome\/b/' old 

sed 's_/home/a_/newhome/b_' old 
sed 's:/home/a:/newhome/b:' old 
sed 's|/home/a|/newhome/b|' old 

매칭 스트링을 표기하기 위해 & 을 사용

매칭되는 스트링을 유지한채 특정 패턴을 더하고 싶을 경우가 있다. 예를 들어 abc 를 (abc) 로 바꾸고 싶다.

echo "abc" > old
sed 's/abc/(abc)/' old
# (abc)

하지만 정확한 패턴을 모른다면 & 으로 사용 할 수 있다.

echo "abc" > old
sed 's/[a-z]*/(&)/' old
# (abc)

& 을 몇번이고 쓸수 있다.

echo "123 abc" > old
sed 's/[0-9]*/& &/' old

새드의 첫번째로 매치하는 패턴을 찾고, 그것에 대해 탐욕적(최대한 매칭 시킬려고 한다.)으로 하려고 한다. 아래와 같은 경우 * 을 사용해 제로 또는 많은을 찾으려고 한다. 아래의 [0-9]*은 0또는 많은 숫자를 찾을려고 하기 때문에 라인의 첫번째 빈공간에 매칭된다(0개의 숫자로 매칭됨) 인풋이 abc 123 일 경우 output은 맨앞의 공간에 빈@빈 == @ 을 추가한다.

echo "abc 123 efg" > old
sed 's/[0-9]*/&@&/' old
# @abc 123 efg

아래와 같이 하면 숫자가 최소 1개 있어야 함으로 123 에 매칭된다. * 은 앞에 표현된 표현식을 매칭시킨다. \, ., a bracket expression 은 매칭되지 않는다.

echo "abc 123 efg" > old
sed 's/[0-9][0-9]*/& &/' old
# abc 123 123 efg

확장 정규 표현형

세드에서 +는 기본적으로 문자열이다. 1개 또는 더를 의미하는 기호로 + 를 사용하려면 새드에 확장 정규형을 사용한다고 명시해 주어야 한다. (mac 은 -E 를 사용)

echo "abc 123 efg" > old
sed -E 's/[0-9]+/& &/' old
# abc 123 123 efg

\1을 이용해 부분 문자열 사용방법

\(regex\) 탈출된 가로를 사용하면 문자열의 일부를 추출해서 메모리에 저장해둔다. 결과에서 \1, \2, ..\9 까지 사용 할 수 있다.

  • 첫번째 단어만 유지 (나머지는 지움)
  • 정규식은 최대한 탐욕적으로 매칭할려고 노력한다.
echo "abc 123 efg" > old
sed 's/\([a-z]*\).*/\1/' old
  • 두단어 치환
echo "abc efg" > old
sed 's/\([a-z]*\) \([a-z]*\)/\2 \1/' old
  • 만약 한글자만 있거나 뒤에 라인이 없으면 검색 패턴을 만족 못함으로 아무것도 안한다.
  • 스페이스만 있으면 * 이기때문에 만족한다.
echo "abc" > old
sed 's/\([a-z]*\) \([a-z]*\)/\2 \1/' old
  • 한단어 이상일때만 치환
  • -E 를 사용하면 탈출 괄호를 사용하지 않는다.
echo "abc d" > old
sed 's/\([a-z][a-z]*\) \([a-z][a-z]*\)/\2 \1/' old

sed -E 's/([a-z]+) ([a-z]+)/\2 \1/' old
  • 패턴에서도 \1 을 사용 할 수 있다.
  • 중복 단어를 없애고 싶다.
echo "abc abc" > old
sed 's/\([a-z]*\) \1/\1/' old
  • 중복 단어가 있는 줄만 출력하고 싶다면
echo "abc abc" > old
sed -n '/\([a-z][a-z]*\) \1/p' old
sed -En '/([a-z]+) \1/p' old
  • 앞 3글자 역순으로
echo "abc abc" > old
sed 's/\(.\)\(.\)\(.\)/\3\2\1/' old

Sed Pattern flags

대부분의 유닉스 명령어는 파일 단위로 동작하며 라인을 한줄씩 읽은 후 처리한다.

/g global 변경

변경 할 경우 디폴트는 제일 첫번째 나오는 단어만 변경이다. g 를 주면 라인에서 매칭되는 모든 패턴을 변경한다.

  • 모든 단어에 ()를 치고 싶다면
echo "abc abc" > old
sed 's/[^ ]*/(&)/g' old

Sed의 작동 순서

들어오는 데이터에만 동작함. 라인을 읽다가 패턴이 매칭되면 변경하고 남은 라인을 읽음. 변경된 라인을 다시 읽지 않음

echo "abc efg" > old
sed 's/abc/abc abc/g' old

/1, 2 매칭 패턴 지정

플래그가 없다면 첫번째 매칭 패턴만 바뀐다. g 가 있다면 모든 매칭 패턴이 바뀐다.

  • 두번째 단어를 없애보자.
echo "abc efg" > old
sed 's/\([a-zA-Z]*\) \([a-zA-Z]*\)/\1 /' old
  • 플래그에 숫자를 쓰면 그 패턴만 변경된다.
  • 두번째 단어 없애기
echo "abc efg hij " > old
sed 's/[a-zA-Z]* //2' old
  • password 에서 2번째 지우기
echo "_fpsd:*:265:265:FPS Daemon:/var/db/fpsd:/usr/bin/false" > old
sed 's/[^:]*:/@:/2' old

/p print

새드는 기본적으로 모든 라인을 출력하고 변환된 라인이 있으면 변환된 라인을 출력한다. -n 을 주면 아무것도 출력하지 않는다. /p 를 주면 변경된 라인을 출력하게 한다.

echo "line1 \n abc efg hij \n line3" > old
sed -n 's/abc/@/p' old