Devin.KR
로그인

리눅스 sed 명령어 사용법 - 문자열 치환 옵션 정리와 실전 예제

개발자 조회 2

이 명령어를 언제 쓰는가

서버 30대의 설정 파일에서 같은 값을 바꿔야 할 때, 배포 스크립트가 템플릿의 자리표시자를 실제 값으로 갈아끼워야 할 때, 500MB 짜리 로그에서 특정 줄 범위만 잘라내야 할 때 sed를 쓴다. 편집기를 열지 않고 규칙으로 파일을 고치는 도구다.

sed 의 값어치는 사람 손을 빼는 데 있다. vi 로 서버마다 열어 고치면 30번 중 한 번은 실수가 나지만, sed 한 줄은 30대에서 정확히 같게 동작한다. 대신 -i 는 원본을 즉시 덮어쓰므로, 먼저 화면으로 확인하고 그다음에 적용하는 순서를 몸에 붙여야 한다.

기본 형식

sed [옵션] '주소범위 명령' 파일
  • 주소범위 — 생략하면 모든 줄. 3(3번 줄), 10,20(범위), /패턴/(패턴이 있는 줄), $(마지막 줄)로 쓴다.
  • 명령s(치환), d(삭제), p(출력), a(뒤에 추가), i(앞에 삽입), c(줄 통째 교체).
  • 가장 많이 쓰는 형태는 치환이다. s/찾을것/바꿀것/g 에서 g한 줄에 여러 번 나와도 전부라는 뜻이다.

자주 쓰는 옵션

옵션의미예시
(없음)결과를 화면에만 출력. 원본은 그대로sed 's/dev/prod/g' app.conf
-i파일을 직접 수정한다sed -i 's/dev/prod/g' app.conf
-i.bak수정하되 원본을 파일.bak 으로 남긴다sed -i.bak 's/dev/prod/g' app.conf
-n자동 출력을 끈다. p 와 짝으로 쓴다sed -n '100,120p' app.log
-E확장 정규식 사용(+, ?, () 를 그대로)sed -E 's/[0-9]+/N/g' a.txt
-e여러 명령을 이어 붙인다sed -e 's/a/b/' -e '/^#/d' a.txt
-f 파일스크립트를 파일에서 읽는다sed -f rules.sed a.txt
-s여러 파일을 각각 별개로 취급sed -s -n '1p' *.log

실전 예제

1. 설정값을 확인하고 나서 바꾼다. 실무에서 sed 를 쓰는 정석 순서다. 첫 줄로 결과를 눈으로 보고, 같은 명령에 -i.bak 만 붙여 적용한다.

sed -E 's/^(max_connections)[[:space:]]*=.*/\1 = 500/' /etc/my.cnf.d/server.cnf | grep max_connections
sudo sed -i.bak -E 's/^(max_connections)[[:space:]]*=.*/\1 = 500/' /etc/my.cnf.d/server.cnf

^ 로 줄 시작을 고정한 이유는 주석 처리된 #max_connections 까지 건드리지 않기 위해서다. 이 앵커가 없으면 주석까지 바뀐다.

2. 거대한 로그에서 특정 구간만 잘라낸다. 몇 GB 짜리 로그를 통째로 열 수 없을 때 쓴다. q 를 붙이면 그 지점에서 읽기를 멈춰 파일 끝까지 훑지 않는다.

sed -n '10000,10200p; 10201q' /var/log/app/application.log

장애 시각으로 자르려면 패턴 범위를 쓴다.

sed -n '/2026-08-25 03:1/,/2026-08-25 03:2/p' /var/log/app/application.log

3. 주석과 빈 줄을 걷어내고 실제 설정만 본다. 수백 줄짜리 설정 파일의 실제 내용을 파악하는 가장 빠른 방법이다.

sed -e 's/#.*//' -e '/^[[:space:]]*$/d' /etc/nginx/nginx.conf

4. 배포 시 템플릿의 자리표시자를 채운다. 경로에 / 가 들어가므로 구분자를 | 로 바꾼 것이 요점이다.

sed -e "s|__APP_HOME__|/opt/app|g" \
    -e "s|__VERSION__|1.4.0|g" \
    app.service.tmpl > /etc/systemd/system/app.service

5. 특정 줄 뒤에 설정을 끼워 넣는다. 파일 끝에 붙이면 안 되고 특정 블록 안에 들어가야 할 때 쓴다.

sudo sed -i '/^\[mysqld\]$/a character-set-server = utf8mb4' /etc/my.cnf.d/server.cnf

6. 여러 서버에 같은 수정을 적용한다. sed 의 본래 값어치가 나오는 지점이다.

for h in web01 web02 web03; do
  ssh "$h" 'sudo sed -i.bak "s/^worker_processes .*/worker_processes auto;/" /etc/nginx/nginx.conf && sudo nginx -t'
done

함정과 주의점

GNU sed 와 macOS(BSD) sed 의 -i 는 문법이 다르다. 리눅스에서 되던 명령이 맥에서 이상한 파일을 만든다.

sed -i 's/a/b/' f.txt      # 리눅스: 정상. macOS: -i 의 인자로 's/a/b/' 를 백업 확장자로 먹는다
sed -i '' 's/a/b/' f.txt   # macOS 에서 백업 없이 수정
sed -i.bak 's/a/b/' f.txt  # 양쪽 모두 동작한다

맥과 리눅스를 오가며 쓰는 스크립트라면 항상 -i.bak 형태로 쓰는 것이 안전하다.

-i 는 확인 절차가 없다. 정규식을 한 글자 잘못 써도 그대로 저장되고, 되돌릴 방법이 없다. 운영 설정 파일에는 반드시 -i.bak 을 붙이고, 붙이지 않을 거라면 먼저 -i 없이 실행해 화면으로 결과를 본다.

치환 대상에 / 가 들어가면 구분자를 바꾼다. s/\/var\/log/\/data\/log/ 처럼 이스케이프를 늘리면 읽기 어려워지고 실수가 늘어난다. sed 는 구분자를 자유롭게 고를 수 있으므로 s|/var/log|/data/log| 로 쓴다.

바꿀 문자열의 & 는 특수문자다. 치환 결과에서 &찾은 문자열 전체로 치환된다. 문자 그대로 넣으려면 \& 로 이스케이프한다. URL 이나 쿼리 문자열을 다룰 때 자주 걸린다.

심볼릭 링크를 -i 로 수정하면 링크가 일반 파일로 바뀐다. GNU sed 는 링크 자체를 새 파일로 대체하기 때문이다. 링크가 가리키는 원본을 고치려면 --follow-symlinks 를 붙인다. /etc/nginx/sites-enabled/ 처럼 링크로 구성된 디렉터리에서 실제로 문제가 된다.

함께 보면 좋은 명령어

  • awk — 열 단위 처리, 조건 계산, 집계는 sed 로 억지로 하지 말고 awk 로 넘긴다.
  • grep — 고칠 대상이 실제로 몇 줄인지 먼저 세어본다. grep -c 로 확인하고 sed 를 친다.
  • diff-i.bak 으로 남긴 백업과 비교해 무엇이 바뀌었는지 확인한다.