Lệnh sed: thay thế chuỗi, xóa dòng và cách dùng tùy chọn -i
Lệnh sed là công cụ Linux đọc tệp từng dòng và thực hiện thay thế, xóa, chèn, nhờ đó bạn có thể sửa giá trị trong tệp cấu hình mà không cần mở trình soạn thảo. Khi chạy sed trên bản sao wp-config.php của WordPress ở máy chủ AlmaLinux 9, chúng tôi đã đổi được tên cơ sở dữ liệu mà vẫn giữ tệp gốc nhờ -i.bak.
Các thông báo lỗi trong bài này được giữ nguyên như khi in ra dưới locale tiếng Anh.
1️⃣ Cách dùng cơ bản của lệnh sed và thay thế bằng s
Lệnh s, được dùng nhiều nhất, thay thế chuỗi theo dạng [s/chuỗi cần tìm/chuỗi mới/]. Lệnh chỉ thay kết quả đầu tiên tìm thấy trên một dòng.
echo 'http://example.com http://example.com/blog' | sed 's/http:/https:/'https://example.com http://example.com/blogĐể thay mọi kết quả trên dòng, hãy thêm cờ g vào cuối.
echo 'http://example.com http://example.com/blog' | sed 's/http:/https:/g'https://example.com https://example.com/blogNếu thêm tên tệp vào cuối, sed đọc tệp đó và in kết quả đã thay. Trên bản sao wp-config-sample.php của WordPress đặt tên wp-config.php, chúng tôi đổi giá trị DB_USER và chỉ kiểm tra dòng đó bằng grep.
sed 's/username_here/wp_user/' wp-config.php | grep DB_USERdefine( 'DB_USER', 'wp_user' );Vì giá trị trong đầu ra đã đổi nên dễ tưởng tệp cũng đổi, nhưng khi chạy không có tùy chọn, sed chỉ in kết quả ra màn hình và giữ nguyên tệp gốc. Khi tìm lại cùng dòng đó trong tệp, giá trị ban đầu vẫn còn.
grep DB_USER wp-config.phpdefine( 'DB_USER', 'username_here' );Để đổi cả tệp gốc, hãy dùng tùy chọn -i ở mục 4️⃣.
2️⃣ Chọn dòng trong sed theo số dòng và mẫu (-n, p)
Không có địa chỉ, lệnh s áp dụng cho mọi dòng, nên để chỉ xử lý một số dòng, hãy viết số dòng hoặc mẫu làm địa chỉ trước lệnh. -n tắt tự động in và p in các dòng đã chọn. Dùng cùng nhau thì chỉ hiện dòng 23.
sed -n '23p' wp-config.phpdefine( 'DB_NAME', 'database_name_here' );Nối hai số dòng bằng dấu phẩy sẽ hiện khoảng đó. Dòng 23 đến 32 là phần chứa thiết lập tên cơ sở dữ liệu, người dùng, mật khẩu và máy chủ.
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' );Nếu viết mẫu giữa các dấu gạch chéo thay cho số dòng, mọi dòng chứa mẫu đó đều được chọn.
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', '' );Lệnh [=] in số của dòng đã chọn. Địa chỉ $ nghĩa là dòng cuối, nên [$=] cho biết tổng số dòng của tệp.
sed -n '/DB_HOST/=' wp-config.php32sed -n '$=' wp-config.php102Địa chỉ cũng có thể đặt trước lệnh s. Bên dưới là kết quả chỉ đổi localhost ở dòng 32 và chỉ in dòng đã đổi bằng cờ p.
sed -n '32s/localhost/127.0.0.1/p' wp-config.phpdefine( 'DB_HOST', '127.0.0.1' );Khi chạy p không có -n, dòng đã chọn hiện thêm một lần. sed đọc từng dòng vào pattern space, chạy lệnh rồi tự động in pattern space, nên dòng 2 đã được p in sẽ xuất hiện lại qua tự động in.
sed '2p' wp-config.php | head -n 4<?php
/**
/**
* The base configuration for WordPressCách đọc và xử lý từng dòng này giống băng chuyền nhà máy đặt từng linh kiện lên bàn làm việc, gia công rồi chuyển sang linh kiện tiếp theo.
Bạn có thể so sánh lần lượt trong sơ đồ bên dưới xem mỗi lệnh in gì trên từng dòng.
3️⃣ Xóa và chèn dòng bằng lệnh sed (d, i, a)
d xóa các dòng đã chọn. Để xem mẫu cấu hình nginx bên dưới mà không có dòng chú thích, hãy chọn các dòng bắt đầu bằng # hoặc chỉ có khoảng trắng trước # bằng mẫu [^ *#].
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;
}
}Nối lệnh bằng dấu chấm phẩy sẽ xóa luôn [^$], nghĩa là dòng trống. Hai dòng trống còn lại sau khi xóa chú thích biến mất, chỉ còn các dòng cấu hình.
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 chèn chữ vào trước dòng đã chọn, a chèn vào sau dòng đã chọn. Kết quả chèn một dòng chú thích trước dòng 1 như bên dưới.
sed '1i # managed by sed' example.conf | head -n 3# managed by sed
# example.com
server {Dễ tưởng rằng chữ thụt lề sau a sẽ giữ cả thụt lề, nhưng GNU sed bỏ qua khoảng trắng ngay sau a và chỉ chèn chữ.
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;
}
}Để giữ thụt lề, hãy thêm dấu gạch chéo ngược sau a. Từ khoảng trắng sau dấu gạch chéo ngược trở đi đều được đưa vào như chữ.
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 thay toàn bộ dòng đã chọn. Bên dưới là bốn dòng đầu của kết quả đổi dòng listen 80 thành 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️⃣ Sửa trực tiếp tệp bằng sed -i và tên tệp sao lưu
-i lưu kết quả vào tệp gốc thay vì in ra màn hình. Chữ viết liền ngay sau -i được thêm vào cuối tên tệp sao lưu. wp-config.php và các tệp khác mà trang web đọc nên được sửa bằng -i.bak để giữ lại tệp gốc.
cp wp-config-sample.php wp-config.phpsed -i.bak 's/database_name_here/wordpress_db/' wp-config.phpChạy với -i thì màn hình không hiện gì, nên hãy kiểm tra tệp bằng 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.bakTệp đã sửa và tệp .bak nằm cạnh nhau. Kích thước giảm 6 byte vì database_name_here được đổi thành wordpress_db ngắn hơn. So sánh hai tệp bằng diff sẽ chỉ thấy dòng đã đổi.
diff wp-config.php.bak wp-config.php23c23
< define( 'DB_NAME', 'database_name_here' );
---
> define( 'DB_NAME', 'wordpress_db' );Dòng đã đổi là một dòng DB_NAME ở dòng 23.
Nếu có nhiều giá trị cần đổi, hãy nối các script bằng -e và chạy một lượt.
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' );Nếu viết liền -i và -e thành [-ie], e bị đọc thành một phần tên sao lưu, và tệp wp-config.phpe xuất hiện như bên dưới.
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 ghi nội dung đã sửa vào tệp mới rồi đổi sang tên gốc, nên số inode của tệp khác nhau trước và sau khi chạy.
ls -i wp-config.php207618887 wp-config.phpsed -i 's/localhost/127.0.0.1/' wp-config.phpls -i wp-config.php207618883 wp-config.phpSố inode từ 207618887 trước khi chạy đã đổi thành 207618883.
Nếu tệp không tồn tại hoặc thiếu tên tệp, sed kết thúc với lỗi bên dưới và không tệp nào bị đổi.
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️⃣ Biểu thức chính quy của sed, đổi dấu phân cách và tùy chọn
🔲 Biểu thức chính quy và đổi dấu phân cách
Khi đổi giá trị chứa dấu gạch chéo như đường dẫn, dấu phân cách của lệnh s lẫn với dấu gạch chéo trong giá trị, nên mỗi dấu gạch chéo trong giá trị cần một dấu gạch chéo ngược.
sed -n 's/\/var\/www\/example.com/\/srv\/www\/example.com/p' example.conf root /srv/www/example.com;Ký tự ngay sau s trở thành dấu phân cách, nên đổi sang | vốn không có trong giá trị sẽ cho cùng kết quả mà không cần dấu gạch chéo ngược.
sed -n 's|/var/www/example.com|/srv/www/example.com|p' example.conf root /srv/www/example.com;Dấu chấm (.) trong mẫu khớp với một ký tự bất kỳ. Bên dưới là kết quả mẫu tìm example.com đã đổi cả exampleXcom.
echo 'exampleXcom example.com' | sed 's/example.com/test.org/g'test.org test.orgĐể tìm dấu chấm đúng nghĩa, hãy đặt dấu gạch chéo ngược phía trước.
echo 'exampleXcom example.com' | sed 's/example\.com/test.org/g'exampleXcom test.orgPhần trong ngoặc được gọi lại trong chuỗi mới bằng [\1]. Với -E, ngoặc và + dùng được mà không cần dấu gạch chéo ngược. Bên dưới là kết quả giữ nguyên số sau listen và thêm default_server.
sed -nE 's/listen ([0-9]+);/listen \1 default_server;/p' example.conf listen 80 default_server;Chạy cùng script mà không có -E thì ngoặc bị đọc thành chữ, và xuất hiện lỗi không có nhóm để gọi lại. Để dùng không có -E, hãy thêm dấu gạch chéo ngược cho ngoặc và +.
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;[&] trong chuỗi mới nghĩa là toàn bộ chữ khớp với mẫu, nên bạn có thể thêm # trước phần khớp để biến dòng đó thành chú thích.
sed -n 's/server_name .*;/# &/p' example.conf # server_name example.com www.example.com;🔲 Tùy chọn của lệnh sed
📌 Tùy chọn chính: kết quả chạy trong bài này
| Tùy chọn | Chức năng | Kết quả trong bài này | |
|---|---|---|---|
| -n | Tắt tự động in và chỉ in các dòng được chọn bằng p | sed -n '23p' chỉ hiện dòng 23; không có -n thì 2p in dòng 2 hai lần | |
| -i | Lưu kết quả vào tệp gốc thay vì màn hình (chữ ngay sau được thêm vào cuối tên sao lưu) | -i.bak tạo wp-config.php.bak; số inode đổi sau khi chạy | |
| -e | Nối nhiều script và chạy một lượt | DB_USER và DB_PASSWORD đổi cùng lúc; viết liền thành -ie sẽ tạo bản sao lưu wp-config.phpe | |
| -E | Dùng biểu thức chính quy mở rộng (không cần dấu gạch chéo ngược cho ngoặc và +) | In listen 80 default_server;; cùng script không có -E báo lỗi [invalid reference] | |
| --follow-symlinks | Cùng với -i, sửa tệp gốc mà liên kết trỏ tới | Không có thì tệp thường thay chỗ liên kết và tệp gốc giữ nguyên; có thì giá trị gốc đổi |
📎 Tùy chọn khác: theo tài liệu hướng dẫn chính thức
| Tùy chọn | Chức năng | |
|---|---|---|
| -f | Đọc script từ tệp rồi chạy | |
| -r | Biểu thức chính quy mở rộng, giống -E (-E khả chuyển hơn) | |
| -s | Xử lý từng tệp riêng thay vì một luồng nối liền | |
| -z | Chia dòng bằng ký tự null thay vì xuống dòng | |
| -u | Đọc đầu vào từng ít một và đẩy đầu ra thường xuyên hơn | |
| --posix | Tắt mọi phần mở rộng GNU | |
| --debug | In quá trình chạy ở dạng chi tiết |
🔲 Trình mô phỏng lệnh sed
Thư mục làm việc của trình mô phỏng bên dưới có bản sao wp-config.php và example.conf. Bạn có thể tự nhập các lệnh đã học và kiểm tra tệp bị -i đổi bằng ls -l và diff.
🔢 FAQ & nội dung đề xuất







ℹ️ Thông báo tiếp thị liên kết
Nội dung trên trang này có chứa liên kết affiliate (tiếp thị liên kết). Khi khách truy cập mua sản phẩm hoặc dịch vụ qua các liên kết này, trang sẽ nhận hoa hồng từ bên bán. Trong quá trình đó, số tiền người mua phải trả (sẽ giảm khi có chương trình khuyến mãi ↓) không hề tăng lên. Giá, khuyến mãi và tình trạng hàng được đăng theo thời điểm viết bài và có thể khác với thực tế, vì vậy hãy kiểm tra lại lần cuối với bên bán trước khi mua. Việc chọn và đánh giá sản phẩm dựa trên tiêu chí riêng của trang; việc có nhận hoa hồng hay không không ảnh hưởng đến thứ tự giới thiệu hay nội dung đánh giá.