Linux Commands: sed (Stream Editor) - A Comprehensive Guide

Linux Commands: sed (Stream Editor) - A Comprehensive Guide

sed là một trình chỉnh sửa dòng (stream editor) xử lý nội dung tệp tin từng dòng một. Nội dung đang được xử lý được lưu trong không gian mẫu (pattern space - bộ đệm), và sau khi xử lý, nó được xuất hoặc sửa đổi theo các tùy chọn được chỉ định. Trừ khi được chuyển hướng để lưu trữ đầu ra, nội dung tệp tin sẽ không thay đổi.

sed chủ yếu được sử dụng để tự động chỉnh sửa một hoặc nhiều tệp tin, đơn giản hóa các thao tác lặp đi lặp lại trên tệp. Nó cũng hỗ trợ biểu thức chính quy; để sử dụng biểu thức chính quy mở rộng, tham số -r nên được thêm vào.

cú pháp: sed [tùy chọn] [lệnh bổ sung] [tệp đầu vào]

Tùy chọn

-n, --quiet, --silent: Vô hiệu hóa tự động in nội dung không gian mẫu
-e [lệnh bổ sung], --expression=[lệnh bổ sung hoặc tập lệnh]: Thêm lệnh bổ sung vào danh sách thực thi của chương trình, cho phép nhiều tùy chọn -e
-f [tệp lệnh bổ sung], --file=[tệp lệnh bổ sung]: Đọc lệnh bổ sung từ một tệp và thêm vào danh sách thực thi của chương trình
-i[hậu tố], --in-place[=hậu tố]: Chỉnh sửa tệp và lưu theo lệnh bổ sung. Nếu có hậu tố, một tệp sao lưu được tạo với tên tệp cộng với hậu tố (tệp có hậu tố là tệp gốc, tệp không có hậu tố là tệp đã sửa đổi)
-c, --copy: Khi tổ chức tệp ở chế độ -i, sử dụng sao chép thay vì đổi tên (điều này liên quan đến số inode của tệp)
-b, --binary: Mở tệp ở chế độ nhị phân, không xử lý đặc biệt cho CR và LFS (yêu cầu thay đổi và hệ thống tệp kết quả nhật ký), để tương thích với WIN32/CYGWIN/MSDOS/EMX
-l N, --line-length=N: Chỉ định độ dài dòng cần thiết cho lệnh bổ sung "l", được hiển thị dưới dạng n-1 chuỗi + \, không có \ ở dòng cuối cùng
--posix: Vô hiệu hóa tất cả mở rộng GNU
-r, --regexp-extended: Sử dụng biểu thức chính quy trong lệnh bổ sung
-s, --separate: Xem xét các tệp như các tệp riêng biệt thay vì một luồng tệp dài liên tục
-u, --unbuffered: Tải lượng dữ liệu tối thiểu từ tệp đầu vào và xóa bộ đệm đầu ra thường xuyên hơn
-z, --null-data: Tách dòng bằng ký tự NUL

Lệnh bổ sung

: [nhãn]: Đặt nhãn cho lệnh bổ sung b và t
b [nhãn]: Nhảy đến nhãn đã chỉ định; nếu không có nhãn theo sau, nhảy đến cuối lệnh bổ sung, kết thúc thực thi cho dòng đó
t [nhãn]: Nếu lệnh s/// (lệnh thay thế) thực thi thành công, nhảy đến nhãn đã chỉ định; nếu không có nhãn theo sau, nhảy đến cuối lệnh bổ sung, kết thúc thực thi cho dòng đó
T [nhãn]: Ngược với t, nhảy đến nhãn đã chỉ định nếu s/// thất bại; nếu không có nhãn theo sau, nhảy đến cuối lệnh bổ sung, kết thúc thực thi cho dòng đó
    Ví dụ: "s/root/xxx/;t a; s/0/1/g;:a" có nghĩa là nếu lệnh thay thế thực thi thành công, lệnh thay thế thứ hai sẽ không được thực thi;
              "/^root/b a; s/0/1/g;:a; s/root/xxx/g" có nghĩa là nếu dòng hiện tại bắt đầu bằng root, không thực hiện lệnh thay thế đầu tiên, thực hiện trực tiếp lệnh thay thế thứ hai
# [lệnh bổ sung]: Ghi chú, nếu nó tồn tại trong tệp lệnh bổ sung, nó tiếp tục đến cuối dòng; nếu nó tồn tại trong lệnh bổ sung, nó tiếp tục đến cuối lệnh
{khối lệnh}: Xem xét nhiều lệnh bổ sung như một toàn thể
[lệnh bổ sung1];[lệnh bổ sung2];...: Dấu chấm phẩy tách lệnh bổ sung, cho phép chỉnh sửa nhiều lệnh cùng một lúc
=: In số dòng
a \[văn bản]: Thêm một hoặc nhiều dòng văn bản sau dòng hiện tại, với ký tự thoát \n cho ngắt dòng trong nhiều dòng
i \[văn bản]: Thêm một hoặc nhiều dòng văn bản trước dòng hiện tại, với ký tự thoát \n cho ngắt dòng trong nhiều dòng
c \[văn bản]: Thay thế dòng hiện tại bằng một hoặc nhiều dòng văn bản, với ký tự thoát \n cho ngắt dòng trong nhiều dòng
    Ví dụ: "1i \[văn bản]" có nghĩa là thêm văn bản trước dòng đầu tiên; "i \[văn bản]" có nghĩa là thêm văn bản trước mỗi dòng
q [mã thoát]: Thoát ngay lập tức khỏi lệnh sed, giá trị thu được bởi $? là mã thoát đã đặt
Q [mã thoát]: Thoát ngay lập tức khỏi lệnh sed, giá trị thu được bởi $? là mã thoát đã đặt
    Lưu ý: Sự khác biệt giữa q và Q là khi tự động in không gian mẫu không bị vô hiệu hóa, q sẽ in không gian mẫu hiện trước khi thoát, trong khi Q thì không
r [tên tệp]: Thêm nội dung của tệp sau dòng hiện tại
R [tên tệp]: Mỗi dòng của tệp được xem như một nội dung riêng biệt, bắt đầu từ dòng được chỉ định, mỗi lần đọc một dòng của tệp đầu vào, thêm nội dung sau dòng đó
    Ví dụ: "1r [tên tệp]" có nghĩa là thêm tất cả nội dung tệp sau dòng đầu tiên của tệp đầu vào; "r [tên tệp]" có nghĩa là thêm tất cả nội dung tệp sau mỗi dòng của tệp đầu vào;
              "1R [tên tệp]" có nghĩa là thêm dòng đầu tiên của tệp sau dòng đầu tiên của tệp đầu vào, ngay cả khi tệp có nhiều dòng, nó chỉ chạy một lần;
              "R [tên tệp]" có nghĩa là bắt đầu từ dòng đầu tiên của tệp đầu vào, nối nội dung dòng tương ứng của tệp cho mỗi dòng cho đến khi một trong tệp đầu vào hoặc nội dung tệp kết thúc;
              "2,4R [tên tệp]" có nghĩa là từ dòng thứ hai đến thứ tư của tệp đầu vào, nối dòng thứ nhất đến thứ ba của nội dung tệp cho mỗi dòng.
d: Xóa không gian mẫu
D: Tương tự như d (có sự khác biệt, nhưng không chắc cách kích hoạt)
h|H: Sao chép hoặc nối nội dung không gian mẫu vào bộ đệm trong bộ nhớ
g|G: Sao chép hoặc nối bộ đệm trong bộ nhớ vào không gian mẫu
l: Hiển thị dòng hiện tại một cách trực quan, không hủy bỏ in mặc định, ký tự thoát sẽ được hiển thị dưới dạng $
l [độ dài]: Hiển thị dòng hiện tại một cách trực quan, chỉ định độ dài để in mỗi lần, và \ được sử dụng làm nối dòng (được tính trong độ dài)
n|N: Đọc hoặc nối dòng tiếp theo vào không gian mẫu, sự khác biệt là đọc sẽ ghi đè nội dung hiện có, trong khi nối thì không
p: In toàn bộ nội dung trong không gian mẫu
P: In dòng đầu tiên trong không gian mẫu
s/[nội dung tìm kiếm (biểu thức chính quy)]/[nội dung thay thế]: Cố gắng khớp nội dung tìm kiếm với nội dung trong không gian mẫu, nếu thành công, thay thế phần khớp. Nội dung thay thế có thể sử dụng ký tự đặc biệt & để đại diện cho nội dung khớp trong không gian mẫu,
    ký tự thoát đặc biệt \1 đến \9 biểu thị các biểu thức con tương ứng được khớp trong biểu thức chính quy. (s/[nội dung tìm kiếm]/[nội dung thay thế]/g có thể thay thế tất cả nội dung khớp)
w [tên tệp]: Ghi nội dung không gian mẫu hiện tại vào tệp được chỉ định
W [tên tệp]: Ghi dòng đầu tiên của không gian mẫu hiện tại vào tệp được chỉ định
x: Trao đổi nội dung của bộ đệm trong bộ nhớ và không gian mẫu

Ví dụ

Lưu ý: Không gian mẫu có thể được xem như bộ đệm mà sed đọc nội dung tệp mỗi lần, mặc định đọc một dòng tại một thời điểm.

Chuẩn bị hai tệp thử nghiệm:

[root@youxi1 ~]# vim readFile
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# vim a.txt
12345
67890

1) Xem các dòng 2 đến 4 của tệp readFile

[root@youxi1 ~]# sed -e "2,4p" readFile -n    // Tùy chọn -e là tùy chọn mặc định, có thể không viết
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# sed "2,4p" readFile    // Nếu không có tùy chọn -n, sed sẽ tự động in nội dung không gian mẫu
root:0:0:root:123456:password
abc:1:1:abc:password1
abc:1:1:abc:password1
xyz:2:2:abc:password2
xyz:2:2:abc:password2
root:3:4:abc:pass
root:3:4:abc:pass

2) Tùy chọn -i và -c, đổi tên và sao chép

# Khi không có tùy chọn -c, tùy chọn -i đổi tên tệp gốc thành tệp sao lưu
[root@youxi1 ~]# ls -i readFile    // Kiểm tra số inode của readFile
33575417 readFile
[root@youxi1 ~]# sed -i.bak "1,2p" readFile -n    // Sử dụng tùy chọn -i để chỉnh sửa và lưu tệp
[root@youxi1 ~]# ls -i readFile    // Ta có thể thấy số inode khác với tệp gốc
33574999 readFile
[root@youxi1 ~]# cat readFile    // Nội dung cũng khác với tệp gốc
root:0:0:root:123456:password
abc:1:1:abc:password1
[root@youxi1 ~]# ls -i readFile.bak    // Tệp sao lưu có cùng số inode với tệp gốc
33575417 readFile.bak
[root@youxi1 ~]# cat readFile.bak    // Nội dung giống với tệp gốc
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
# Khi sử dụng tùy chọn -i kết hợp với tùy chọn -c
[root@youxi1 ~]# sed -i.cp "1,2p" readFile.bak -n -c
[root@youxi1 ~]# ls -i readFile.bak    // Ta có thể thấy số inode giống với tệp gốc
33575417 readFile.bak
[root@youxi1 ~]# cat readFile.bak    // Nội dung khác với tệp gốc
root:0:0:root:123456:password
abc:1:1:abc:password1
[root@youxi1 ~]# ls -i readFile.bak.cp    // Tệp sao lưu có số inode khác với tệp gốc
34037099 readFile.bak.cp
[root@youxi1 ~]# cat readFile.bak.cp    // Nội dung giống với tệp gốc
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass

3) Lệnh bổ sung a \[văn bản\], i \[văn bản\], c \[văn bản\]

[root@youxi1 ~]# rm -rf readFile readFile.bak
[root@youxi1 ~]# mv readFile.bak.cp readFile
[root@youxi1 ~]# cat readFile
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# sed "1a \add" readFile    // Thêm dưới dòng đầu tiên
root:0:0:root:123456:password
add
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# sed "1i \add" readFile    // Thêm trên dòng đầu tiên
add
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# sed "1c \add" readFile    // Thay thế dòng đầu tiên
add
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# sed "1c \add\nabc\t123 456" readFile    // Ký tự thoát cho ngắt dòng \n và tab \t
add
abc 123 456
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass

4) Lệnh bổ sung =, in số dòng

[root@youxi1 ~]# sed "=" readFile
1
root:0:0:root:123456:password
2
abc:1:1:abc:password1
3
xyz:2:2:abc:password2
4
root:3:4:abc:pass

5) Lệnh bổ sung d

[root@youxi1 ~]# sed "1,2d" readFile
xyz:2:2:abc:password2
root:3:4:abc:pass

6) Lệnh bổ sung s/[nội dung tìm kiếm]/[nội dung thay thế]/(g)

[root@youxi1 ~]# sed "s/root/xxx/" readFile    // Thay thế lần khớp đầu tiên
xxx:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
xxx:3:4:abc:pass
[root@youxi1 ~]# sed "s/root/xxx/g" readFile    // Thay thế tất cả các lần khớp
xxx:0:0:xxx:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
xxx:3:4:abc:pass
[root@youxi1 ~]# sed "s/a.*p/1234/" readFile    // Khớp biểu thức chính quy và thay thế
root:0:0:root:123456:password
1234assword1
xyz:2:2:1234assword2
root:3:4:1234ass
[root@youxi1 ~]# sed "s/a.*p/&1234/" readFile    // Khớp biểu thức chính quy, giữ nguyên và thêm thay thế
root:0:0:root:123456:password
abc:1:1:abc:p1234assword1
xyz:2:2:abc:p1234assword2
root:3:4:abc:p1234ass
Bạn cũng có thể thêm một số trước s để chỉ định bắt đầu từ dòng nào để tìm kiếm.

7) Tùy chọn -r, sử dụng biểu thức chính quy để khớp các dòng cụ thể

[root@youxi1 ~]# sed -r "/^root/i \1234" readFile    // Tìm dòng được chỉ định, thêm nội dung trên nó
1234
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
1234
root:3:4:abc:pass
[root@youxi1 ~]# sed "/^.*abc/{s/^.*$/&\tName/}" readFile    // Tùy chọn -r có thể được bỏ qua
root:0:0:root:123456:password
abc:1:1:abc:password1   Name
xyz:2:2:abc:password2   Name
root:3:4:abc:pass       Name
[root@youxi1 ~]# sed "/^.*abc/s/^.*$/&\tName/" readFile    // Ngay cả {} cũng có thể được bỏ qua, nhưng không nên vì không dễ hiểu
root:0:0:root:123456:password
abc:1:1:abc:password1   Name
xyz:2:2:abc:password2   Name
root:3:4:abc:pass       Name

8) Lệnh bổ sung q, Q

[root@youxi1 ~]# sed "/^.*abc/q" readFile  
root:0:0:root:123456:password
abc:1:1:abc:password1
[root@youxi1 ~]# sed "/^.*abc/Q" readFile 
root:0:0:root:123456:password

9) Lệnh bổ sung r [tên tệp], R [tên tệp]

[root@youxi1 ~]# sed "/^root/r a.txt" readFile 
root:0:0:root:123456:password
12345
67890
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
12345
67890
[root@youxi1 ~]# sed "/^root/R a.txt" readFile  
root:0:0:root:123456:password
12345
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
67890

10) Lệnh bổ sung n, N, p, P, w, W

Đầu tiên, điều quan trọng là hiểu n (đọc dòng tiếp theo vào không gian mẫu), N (nối dòng tiếp theo vào không gian mẫu), và hành động mặc định của việc in không gian mẫu (chuẩn bị đọc dòng tiếp theo, kết thúc lệnh sed). Lưu ý: Các dòng đọc hoặc nối vào không gian mẫu không còn được đọc bởi các lệnh sed.
[root@youxi1 ~]# sed "n;p" readFile 
root:0:0:root:123456:password    // Chuẩn bị thực hiện lệnh bổ sung n, kích hoạt in mặc định không gian mẫu hiện tại. Sau khi n thực thi, nội dung không gian mẫu là dòng thứ hai
abc:1:1:abc:password1    // Thực hiện lệnh bổ sung p, in không gian mẫu hiện tại, nội dung không gian mẫu không thay đổi
abc:1:1:abc:password1    // Lệnh sed chuẩn bị đọc dòng tiếp theo, kích hoạt in mặc định không gian mẫu hiện tại. Sau khi đọc dòng tiếp theo, nội dung không gian mẫu là dòng thứ ba
xyz:2:2:abc:password2    // Chuẩn bị thực hiện lệnh bổ sung n, kích hoạt in mặc định không gian mẫu hiện tại. Sau khi n thực thi, nội dung không gian mẫu là dòng thứ tư
root:3:4:abc:pass    // Thực hiện lệnh bổ sung p, in không gian mẫu hiện tại, nội dung không gian mẫu không thay đổi
root:3:4:abc:pass    // Lệnh sed kết thúc, in không gian mẫu hiện tại (hành động này để làm sạch không gian mẫu?)
[root@youxi1 ~]# sed "N;p" readFile   
root:0:0:root:123456:password
abc:1:1:abc:password1    // Thực hiện lệnh bổ sung N, nội dung không gian mẫu là dòng thứ nhất và thứ hai; thực hiện lệnh bổ sung p, in không gian mẫu hiện tại
root:0:0:root:123456:password
abc:1:1:abc:password1    // Lệnh sed chuẩn bị đọc dòng tiếp theo, kích hoạt in mặc định không gian mẫu hiện tại. Sau khi đọc dòng tiếp theo, nội dung không gian mẫu là dòng thứ ba
xyz:2:2:abc:password2
root:3:4:abc:pass    // Thực hiện lệnh bổ sung N, nội dung không gian mẫu thay đổi từ dòng thứ ba thành dòng thứ ba và thứ tư; thực hiện lệnh bổ sung p, in không gian mẫu hiện tại
xyz:2:2:abc:password2
root:3:4:abc:pass    // Lệnh sed kết thúc, in không gian mẫu hiện tại (hành động này để làm sạch không gian mẫu?)
Tiếp theo, hiểu p (in không gian mẫu hiện tại) và P (in dòng đầu tiên trong không gian mẫu). Với sự hiểu biết về n và N, những điều này cũng dễ hiểu.
[root@youxi1 ~]# sed "N;p" readFile -n
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# sed "N;P" readFile -n 
root:0:0:root:123456:password
xyz:2:2:abc:password2
Cuối cùng là w (lưu không gian mẫu hiện tại vào tệp được chỉ định) và W (lưu dòng đầu tiên của không gian mẫu hiện tại vào tệp được chỉ định), sự khác biệt với p và P là chúng không in, trực tiếp lưu vào tệp. Hiểu p và P, những điều này cũng đơn giản.
[root@youxi1 ~]# sed "N;w b.txt" readFile -n
[root@youxi1 ~]# sed "N;W c.txt" readFile -n
[root@youxi1 ~]# cat b.txt
root:0:0:root:123456:password
abc:1:1:abc:password1
xyz:2:2:abc:password2
root:3:4:abc:pass
[root@youxi1 ~]# cat c.txt
root:0:0:root:123456:password
xyz:2:2:abc:password2

sed Create, Read, Update, Delete (CRUD)

Các lệnh sed phổ biến nhất là bốn thao tác CRUD: "Create" (Tạo) có thể sử dụng lệnh bổ sung a \[văn bản\], i \[văn bản\], r [tên tệp] và R [tên tệp]; "Delete" (Xóa) có thể sử dụng lệnh bổ sung d; "Update" (Cập nhật) có thể sử dụng lệnh bổ sung c \[văn bản\] và s/[nội dung tìm kiếm]/[nội dung thay thế]/; "Read" (Đọc) có thể sử dụng tùy chọn -r và lệnh bổ sung p.

Thẻ: linux sed stream editor text processing regular expressions

Đăng vào ngày 4 tháng 6 lúc 18:19