sed 명령어: 문자열 치환, 줄 삭제와 -i 옵션 사용법

sed 명령어는 파일 내용을 한 줄씩 읽어 바꾸기와 지우기, 넣기를 실행하는 리눅스 도구로, 편집기를 열지 않고 설정 파일의 값을 고칠 수 있습니다. AlmaLinux 9 서버에서 워드프레스 wp-config.php 사본에 sed를 실행한 결과, -i.bak으로 원본을 남긴 채 데이터베이스 이름을 바꿀 수 있었습니다.
글에 실은 오류 문구는 영어 locale에서 출력한 그대로입니다.
1️⃣ sed 명령어 기본 사용법과 s 치환
가장 많이 사용하는 s 명령은 [s/찾을 문자열/바꿀 문자열/] 형식으로 문자열을 치환합니다. 한 줄에서 처음 찾은 하나만 바꿉니다.
echo 'http://example.com http://example.com/blog' | sed 's/http:/https:/'https://example.com http://example.com/blog줄 안의 모든 문자열을 바꾸려면 끝에 g 플래그를 붙입니다.
echo 'http://example.com http://example.com/blog' | sed 's/http:/https:/g'https://example.com https://example.com/blog파일 이름을 뒤에 붙이면 그 파일을 읽어 바꾼 결과를 출력합니다. 워드프레스의 wp-config-sample.php를 wp-config.php로 복사한 사본에서 DB_USER 값을 바꾸고, grep으로 그 줄만 확인했습니다.
sed 's/username_here/wp_user/' wp-config.php | grep DB_USERdefine( 'DB_USER', 'wp_user' );출력에서 값이 바뀌었으니 파일도 바뀌었다고 여기기 쉬우나, sed는 옵션 없이 실행하면 결과를 화면에만 출력하고 원본 파일은 그대로 둡니다. 같은 줄을 파일에서 다시 찾아보니 처음 값이 그대로 남아 있었습니다.
grep DB_USER wp-config.phpdefine( 'DB_USER', 'username_here' );원본 파일까지 바꾸려면 4️⃣의 -i 옵션을 사용합니다.
2️⃣ sed 줄 번호와 패턴으로 줄 고르기(-n, p)
s 명령은 주소 없이 실행하면 모든 줄에 적용되므로, 특정 줄만 다루려면 명령 앞에 줄 번호나 패턴을 주소로 적습니다. -n은 자동 출력을 끄고 p는 고른 줄을 출력합니다. 둘을 함께 쓰면 23행 하나만 나옵니다.
sed -n '23p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );쉼표로 두 줄 번호를 이으면 그 범위가 나옵니다. 23행부터 32행까지는 데이터베이스 이름과 사용자, 비밀번호, 호스트 설정이 들어 있는 구간입니다.
sed -n '23,32p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );
/** Database username */
define( 'DB_USER', 'username_here' );
/** Database password */
define( 'DB_PASSWORD', 'password_here' );
/** Database hostname */
define( 'DB_HOST', 'localhost' );줄 번호 대신 슬래시 사이에 패턴을 적으면 그 패턴이 들어 있는 줄을 모두 고릅니다.
sed -n '/DB_/p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );
define( 'DB_USER', 'username_here' );
define( 'DB_PASSWORD', 'password_here' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );[=] 명령은 고른 줄의 번호를 출력합니다. 주소 $는 마지막 줄을 의미하므로 [$=]로 파일 전체 줄 수를 확인할 수 있습니다.
sed -n '/DB_HOST/=' wp-config.php32sed -n '$=' wp-config.php102주소는 s 명령 앞에도 붙일 수 있습니다. 아래는 32행에서만 localhost를 바꾸고 p 플래그로 바뀐 줄만 출력한 결과입니다.
sed -n '32s/localhost/127.0.0.1/p' wp-config.phpdefine( 'DB_HOST', '127.0.0.1' );-n 없이 p를 실행해 보니 고른 줄이 한 번 더 나왔습니다. sed는 줄을 하나씩 패턴 공간에 읽어 명령을 실행한 뒤 패턴 공간을 자동으로 출력하므로, p로 출력한 2행이 자동 출력으로 다시 나옵니다.
sed '2p' wp-config.php | head -n 4<?php
/**
/**
* The base configuration for WordPress줄을 하나씩 읽어 처리하는 이 방식은 공장 컨베이어 벨트가 부품을 하나씩 작업대에 올려 가공한 뒤 다음 부품으로 넘기는 것과 같습니다.
명령에 따라 줄마다 무엇이 출력되는지는 아래 다이어그램에서 차례로 비교할 수 있습니다.
3️⃣ sed 명령어 줄 삭제와 삽입(d, i, a)
d는 고른 줄을 지우는 명령입니다. 아래 nginx 설정 견본에서 주석 줄을 빼고 보려면, #으로 시작하거나 # 앞에 공백만 있는 줄을 [^ *#] 패턴으로 고릅니다.
cat example.conf# example.com
server {
listen 80;
server_name example.com www.example.com;
# document root
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}sed '/^ *#/d' example.confserver {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}세미콜론으로 명령을 이으면 빈 줄을 의미하는 [^$]까지 함께 지웁니다. 주석 줄을 지운 결과에 남아 있던 빈 줄 두 개가 사라지고 설정 줄만 남았습니다.
sed '/^ *#/d; /^$/d' example.confserver {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
}i는 고른 줄 앞에, a는 고른 줄 뒤에 글자를 넣습니다. 1행 앞에 주석 한 줄을 넣은 결과는 아래와 같습니다.
sed '1i # managed by sed' example.conf | head -n 3# managed by sed
# example.com
server {a 뒤에 들여쓰기한 글자를 적으면 들여쓰기도 함께 들어간다고 여기기 쉬우나, GNU sed는 a 바로 뒤 공백을 건너뛰고 글자만 넣습니다.
sed '/index index.php/a client_max_body_size 64M;' example.conf# example.com
server {
listen 80;
server_name example.com www.example.com;
# document root
root /var/www/example.com;
index index.php index.html;
client_max_body_size 64M;
location / {
try_files $uri $uri/ /index.php?$args;
}
}들여쓰기를 지키려면 a 뒤에 역슬래시를 붙입니다. 역슬래시 뒤 공백부터 글자로 들어갑니다.
sed '/index index.php/a\ client_max_body_size 64M;' example.conf# example.com
server {
listen 80;
server_name example.com www.example.com;
# document root
root /var/www/example.com;
index index.php index.html;
client_max_body_size 64M;
location / {
try_files $uri $uri/ /index.php?$args;
}
}c는 고른 줄을 통째로 바꾸는 명령입니다. 아래는 listen 80 줄을 8080으로 바꾼 결과의 앞 네 줄입니다.
sed '/listen 80;/c\ listen 8080;' example.conf | head -n 4# example.com
server {
listen 8080;
server_name example.com www.example.com;4️⃣ sed -i 파일 직접 수정과 백업 파일 이름
-i는 결과를 화면 대신 원래 파일에 저장하는 옵션입니다. -i 바로 뒤에 붙인 글자는 백업 파일 이름 끝에 붙습니다. wp-config.php처럼 사이트가 읽는 파일은 -i.bak으로 원본을 남겨 두고 고칩니다.
cp wp-config-sample.php wp-config.phpsed -i.bak 's/database_name_here/wordpress_db/' wp-config.php-i로 실행하면 화면에는 아무것도 출력되지 않으므로, ls -l로 파일을 확인합니다.
ls -l wp-config.php*-rw-r--r-- 1 root root 3333 Oct 28 15:13 wp-config.php
-rw-r--r-- 1 root root 3339 Oct 28 15:13 wp-config.php.bak고친 파일과 .bak 파일이 함께 생겼습니다. database_name_here가 wordpress_db로 줄어든 만큼 크기가 6바이트 작아졌습니다. diff로 두 파일을 비교하면 바뀐 줄만 확인할 수 있습니다.
diff wp-config.php.bak wp-config.php23c23
< define( 'DB_NAME', 'database_name_here' );
---
> define( 'DB_NAME', 'wordpress_db' );바뀐 줄은 23행의 DB_NAME 한 줄입니다.
바꿀 값이 여럿이면 -e로 스크립트를 이어 한 번에 실행합니다.
sed -i -e 's/username_here/wp_user/' -e 's/password_here/wp_pass/' wp-config.phpgrep -n -e DB_USER -e DB_PASSWORD wp-config.php26:define( 'DB_USER', 'wp_user' );
29:define( 'DB_PASSWORD', 'wp_pass' );-i와 -e를 [-ie]처럼 붙여 쓰면 e까지 백업 이름으로 읽혀, 아래처럼 wp-config.phpe 파일이 생겼습니다.
sed -ie 's/127.0.0.1/localhost/' wp-config.phpls wp-config.php*wp-config.php
wp-config.php.bak
wp-config.phpe-i는 고친 내용을 새 파일에 쓴 뒤 원래 이름으로 바꿔 넣으므로, 실행 전후 파일의 inode 번호가 달라집니다.
ls -i wp-config.php207618887 wp-config.phpsed -i 's/localhost/127.0.0.1/' wp-config.phpls -i wp-config.php207618883 wp-config.php실행 전 207618887이던 inode 번호가 207618883으로 바뀌었습니다.
파일이 없거나 파일 이름을 빠뜨리면 아래 오류로 끝나고 아무 파일도 바뀌지 않습니다.
sed -i 's/x/y/' no-such.phpsed: can't read no-such.php: No such file or directorysed -i 's/x/y/'sed: no input files5️⃣ sed 명령어 정규식, 구분자 변경과 옵션
🔲 정규식과 구분자 변경
경로처럼 슬래시가 든 값을 바꾸면 s 명령의 구분자와 값의 슬래시가 섞이므로, 값의 슬래시마다 역슬래시를 붙여야 합니다.
sed -n 's/\/var\/www\/example.com/\/srv\/www\/example.com/p' example.conf root /srv/www/example.com;s 바로 뒤 글자가 구분자가 되므로, 값에 없는 | 로 바꾸면 역슬래시 없이 같은 결과가 나옵니다.
sed -n 's|/var/www/example.com|/srv/www/example.com|p' example.conf root /srv/www/example.com;패턴의 점(.)은 아무 글자 하나와 맞습니다. 아래는 example.com을 찾는 패턴이 exampleXcom까지 바꾼 결과입니다.
echo 'exampleXcom example.com' | sed 's/example.com/test.org/g'test.org test.org점을 글자 그대로 찾으려면 앞에 역슬래시를 붙입니다.
echo 'exampleXcom example.com' | sed 's/example\.com/test.org/g'exampleXcom test.org괄호로 묶은 부분은 바꿀 문자열에서 [\1]로 다시 불러옵니다. -E를 붙이면 괄호와 +를 역슬래시 없이 사용합니다. 아래는 listen 뒤 숫자를 그대로 두고 default_server를 덧붙인 결과입니다.
sed -nE 's/listen ([0-9]+);/listen \1 default_server;/p' example.conf listen 80 default_server;-E 없이 같은 스크립트를 실행하면 괄호를 글자로 읽어, 불러올 묶음이 없다는 오류가 납니다. -E 없이 사용하려면 괄호와 +에 역슬래시를 붙입니다.
sed -n 's/listen ([0-9]+);/listen \1 default_server;/p' example.confsed: -e expression #1, char 46: invalid reference \1 on `s' command's RHSsed -n 's/listen \([0-9]\+\);/listen \1 default_server;/p' example.conf listen 80 default_server;바꿀 문자열의 [&]는 패턴에 맞은 글자 전체를 의미하므로, 맞은 부분 앞에 # 를 붙여 그 줄을 주석으로 만들 수 있습니다.
sed -n 's/server_name .*;/# &/p' example.conf # server_name example.com www.example.com;🔲 sed 명령어 옵션
📌 주요 옵션: 이 글에서 실행한 결과
| 옵션 | 하는 일 | 이 글에서 본 결과 | |
|---|---|---|---|
| -n | 자동 출력을 끄고 p로 고른 줄만 출력 | sed -n '23p'로 23행 한 줄만 나옴, -n 없이 2p는 2행이 두 번 | |
| -i | 결과를 화면 대신 원래 파일에 저장(바로 뒤 글자는 백업 이름 끝에 붙음) | -i.bak으로 wp-config.php.bak이 생김, 실행 뒤 inode 번호가 바뀜 | |
| -e | 스크립트 여러 개를 이어 한 번에 실행 | DB_USER와 DB_PASSWORD 두 값이 한 번에 바뀜, -ie로 붙이면 wp-config.phpe 백업이 생김 | |
| -E | 확장 정규식 사용(괄호와 +에 역슬래시 없이) | listen 80 default_server; 출력, -E 없이 같은 스크립트는 [invalid reference] 오류 | |
| --follow-symlinks | -i와 함께 링크가 가리키는 원본 파일을 고침 | 없으면 링크 자리에 일반 파일이 생기고 원본 그대로, 붙이면 원본 값이 바뀜 |
📎 그 밖의 옵션: 공식 매뉴얼 기준
| 옵션 | 하는 일 | |
|---|---|---|
| -f | 스크립트를 파일에서 읽어 실행 | |
| -r | -E와 같은 확장 정규식(이식성은 -E) | |
| -s | 여러 파일을 이어진 하나가 아니라 파일마다 따로 처리 | |
| -z | 줄을 줄바꿈 대신 널 문자로 나눔 | |
| -u | 입력을 조금씩 읽고 출력을 더 자주 내보냄 | |
| --posix | GNU 확장 기능을 모두 끔 | |
| --debug | 실행 과정을 풀어서 출력 |
🔲 sed 명령어 시뮬레이터
아래 시뮬레이터의 작업 폴더에는 wp-config.php 사본과 example.conf가 있습니다. 지금까지의 명령을 직접 입력하고, -i로 바뀐 파일은 ls -l과 diff로 확인할 수 있습니다.
🔢 FAQ & 추천 콘텐츠







ℹ️ 제휴 안내
본 사이트의 콘텐츠에는 제휴 링크가 포함되어 있습니다. 방문자가 이 링크를 통해 상품 또는 서비스를 구매하면 본 사이트는 판매처로부터 수수료를 지급받습니다. 이 과정에서 구매자가 지불하는 금액(이벤트 할인 시 금액이 내려갑니다↓)은 오르지 않습니다. 게시된 가격·할인·재고 정보는 작성 시점 기준이며 실제와 다를 수 있으므로, 구매 전 판매처에서 최종 확인하시기 바랍니다. 상품 선정과 평가는 자체 기준에 따라 작성되며, 수수료 지급 여부가 소개 순서나 평가 내용에 영향을 주지 않습니다.