Hướng Dẫn Cơ Bản Sử Dụng Sed – Stream Editor Mạnh Mẽ Trong Linux

huong dan su dung sed stream editor trong

Lệnh sed (viết tắt của stream editor) thực hiện các thao tác chỉnh sửa trên văn bản lấy từ đầu vào tiêu chuẩn (STDIN) hoặc từ một tệp tin. Sed tiến hành chỉnh sửa theo từng dòng và theo cách không tương tác – nghĩa là bạn đưa ra tất cả các quyết định chỉnh sửa khi gọi lệnh, và sed sẽ tự động thực thi theo chỉ dẫn đó. Mặc dù có thể ban đầu cảm thấy hơi khó hiểu hoặc không trực quan, nhưng đây là một phương pháp rất mạnh mẽ và nhanh chóng để biến đổi văn bản, đặc biệt là khi tích hợp vào trong các script hay quy trình tự động.

Nếu bạn đang tìm kiếm một giải pháp lưu trữ mạnh mẽ và linh hoạt cho các dự án Linux, hãy khám phá dịch vụ VPS Hosting của chúng tôi. Với hiệu suất cao và khả năng tùy chỉnh linh hoạt, VPS Hosting là lựa chọn lý tưởng cho cả nhà phát triển và doanh nghiệp.

Hướng dẫn này sẽ giới thiệu một số thao tác cơ bản và cung cấp cho bạn cú pháp cần thiết để vận hành trình chỉnh sửa này. Bạn hẳn sẽ không bao giờ thay thế trình soạn thảo văn bản thông thường bằng sed, nhưng chắc chắn nó sẽ trở thành một công cụ hữu ích được bổ sung vào bộ công cụ chỉnh sửa văn bản của bạn.

Lưu ý: Hướng dẫn này sử dụng phiên bản GNU của sed được tìm thấy trên Ubuntu và các hệ điều hành Linux khác. Nếu bạn đang dùng macOS, bạn sẽ có phiên bản BSD với các tùy chọn và đối số khác. Bạn có thể cài đặt phiên bản GNU của sed với Homebrew bằng lệnh brew install gnu-sed.

Sử dụng cơ bản

Sed vận hành trên một dòng văn bản mà nó đọc từ một tệp tin văn bản hoặc từ đầu vào tiêu chuẩn (STDIN). Điều này có nghĩa là bạn có thể chuyển đầu ra của một lệnh khác trực tiếp cho sed để chỉnh sửa, hoặc bạn có thể làm việc trên một tệp tin đã có sẵn.

Bạn cũng nên lưu ý rằng sed sẽ xuất mọi thứ ra đầu ra tiêu chuẩn (STDOUT) theo mặc định. Điều đó có nghĩa là, nếu không chuyển hướng, sed sẽ in kết quả ra màn hình thay vì lưu vào tệp.

Cú pháp cơ bản là:

sed [options] commands [file-to-edit]

Trong hướng dẫn này, bạn sẽ sử dụng một bản sao của BSD Software License để thử nghiệm với sed. Trên Ubuntu, hãy thực hiện các lệnh sau để sao chép tệp BSD license vào thư mục chính của bạn để có thể thao tác với nó:

cd
cp /usr/share/common-licenses/BSD

Nếu bạn không có bản sao cục bộ của BSD license, hãy tự tạo một bằng lệnh sau:

cat << 'EOF' > BSD
Copyright (c) The Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
EOF

Sử dụng sed để xem nội dung tệp BSD license

Hãy sử dụng sed để xem nội dung của tệp BSD license. Theo mặc định, sed sẽ gửi kết quả ra màn hình, điều đó có nghĩa là bạn có thể sử dụng nó như một trình đọc tệp mà không cần chỉ định lệnh chỉnh sửa nào. Thử thực hiện lệnh sau:

sed '' BSD

Kết quả bạn sẽ thấy là nội dung của BSD license được hiển thị ra màn hình:

Output

Copyright (c) The Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
...
...

Các dấu nháy đơn chứa các lệnh chỉnh sửa mà bạn truyền cho sed. Trong trường hợp này, bạn không truyền gì nên sed in từng dòng mà nó nhận được ra đầu ra tiêu chuẩn.

Sed có thể sử dụng đầu vào tiêu chuẩn thay vì một tệp. Hãy chuyển đầu ra của lệnh cat vào sed để tạo ra cùng kết quả:

cat BSD | sed ''

Kết quả in ra cũng sẽ giống như nội dung của tệp BSD.

Copyright (c) The Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
. . .
. . .

In dòng

Trong ví dụ trước, bạn đã thấy rằng đầu vào chuyển cho sed mà không có bất kỳ thao tác nào sẽ được in ra trực tiếp. Bây giờ hãy khám phá lệnh in dòng (print) của sed, mà bạn chỉ định bằng cách sử dụng ký tự p trong dấu nháy đơn.

Thực hiện lệnh sau:

sed 'p' BSD

Kết quả, bạn sẽ thấy mỗi dòng của tệp BSD được in ra hai lần:

Output

Copyright (c) The Regents of the University of California.
Copyright (c) The Regents of the University of California.
All rights reserved.
All rights reserved.


Redistribution and use in source and binary forms, with or without
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
modification, are permitted provided that the following conditions
are met:
are met:
. . .
. . .

Sed tự động in mỗi dòng theo mặc định, và khi bạn yêu cầu in thêm với lệnh p, kết quả là mỗi dòng được in ra hai lần.

Nếu bạn muốn tránh việc in dòng tự động, bạn có thể sử dụng tùy chọn -n để tắt việc in tự động:

sed -n 'p' BSD

Output

Copyright (c) The Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
. . .
. . .

Giờ đây, mỗi dòng chỉ được in ra một lần.

Sử dụng khoảng địa chỉ

Khoảng địa chỉ (addresses) cho phép bạn chọn những phần cụ thể của dòng văn bản để thao tác. Bạn có thể chỉ định một dòng cụ thể hoặc một khoảng dòng.

Ví dụ, hãy để sed in ra dòng đầu tiên của tệp. Thực hiện lệnh:

sed -n '1p' BSD

Dòng đầu tiên sẽ được in ra màn hình:

Output

Copyright (c) The Regents of the University of California.

Bằng cách đặt số 1 trước lệnh in, bạn đã chỉ định cho sed thao tác trên dòng số 1. Bạn cũng có thể in ra 5 dòng đầu tiên (đừng quên sử dụng -n):

sed -n '1,5p' BSD

Output

Copyright (c) The Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

Bạn vừa cung cấp một khoảng địa chỉ cho sed. Ngoài ra, bạn có thể chỉ định khoảng cách bằng cách cho số dòng ban đầu và sau đó dùng offset để chỉ định số dòng tiếp theo, ví dụ:

sed -n '1,+4p' BSD

Kết quả sẽ tương tự vì bạn yêu cầu sed bắt đầu từ dòng 1 và thao tác trên 4 dòng tiếp theo.

Nếu bạn muốn in mỗi dòng cách nhau một khoảng (ví dụ in từng dòng chẵn hoặc lẻ), bạn có thể chỉ định khoảng cách sau ký hiệu ~. Lệnh sau in mỗi dòng thứ 2 của tệp BSD, bắt đầu từ dòng 1:

sed -n '1~2p' BSD

Output

Copyright (c) The Regents of the University of California.

modification, are permitted provided that the following conditions
1. Redistributions of source code must retain the above copyright
2. Redistributions in binary form must reproduce the above copyright
    documentation and/or other materials provided with the distribution.
    may be used to endorse or promote products derived from this software
. . .
. . .

Xóa văn bản

Bạn có thể sử dụng sed để xóa văn bản khỏi đầu ra. Thay vì sử dụng lệnh p (in), bạn chuyển sang sử dụng lệnh d (delete).

Khi sử dụng lệnh d, bạn không cần phải dùng tùy chọn -n vì sed sẽ tự động in ra những dòng không bị xóa, giúp bạn dễ dàng quan sát kết quả.

Hãy chỉnh sửa lệnh in mỗi dòng cách nhau một khoảng từ phần trước để xóa mỗi dòng thứ nhất (và cứ thế mỗi dòng cách đều):

sed '1~2d' BSD

Kết quả là bạn sẽ thấy chỉ những dòng không bị xóa được in ra:

Output

All rights reserved.
Redistribution and use in source and binary forms, with or without
are met:
    notice, this list of conditions and the following disclaimer.
    notice, this list of conditions and the following disclaimer in the
3. Neither the name of the University nor the names of its contributors
    without specific prior written permission.
. . .
. . .

Lưu ý rằng tệp nguồn không bị thay đổi – các chỉnh sửa chỉ xuất ra màn hình. Nếu bạn muốn lưu các chỉnh sửa, bạn có thể chuyển hướng đầu ra tiêu chuẩn vào một tệp, ví dụ:

sed '1~2d' BSD > everyother.txt

Sau đó, mở tệp bằng lệnh:

cat everyother.txt

Kết quả sẽ giống như đầu ra bạn đã thấy.

All rights reserved.
Redistribution and use in source and binary forms, with or without
are met:
    notice, this list of conditions and the following disclaimer.
    notice, this list of conditions and the following disclaimer in the
3. Neither the name of the University nor the names of its contributors
    without specific prior written permission.
. . .
. . .

Mặc định, sed không chỉnh sửa tệp nguồn, nhưng bạn có thể thay đổi hành vi này bằng cách sử dụng tùy chọn -i (“in-place”), nghĩa là thực hiện chỉnh sửa trực tiếp lên tệp nguồn.

Warning: Sử dụng tùy chọn -i sẽ ghi đè lên tệp gốc, vì vậy hãy cẩn thận. Hãy thử thao tác mà không dùng -i trước, sau đó chạy lại với -i khi bạn đã có kết quả mong muốn, hoặc tạo một bản sao lưu của tệp gốc, hoặc chuyển hướng đầu ra vào một tệp mới. Rất dễ xảy ra tình huống bạn vô tình thay đổi tệp gốc khi dùng -i.

Hãy thử chỉnh sửa tệp everyother.txt vừa tạo, trực tiếp tại chỗ. Giảm kích thước tệp thêm bằng cách xóa mỗi dòng cách nhau một khoảng:

sed -i '1~2d' everyother.txt

Sau đó, nếu bạn dùng cat everyother.txt để xem nội dung, bạn sẽ thấy tệp đã được chỉnh sửa.

Tùy chọn -i có thể gây nguy hiểm. May mắn thay, sed cho phép bạn tạo một tệp sao lưu trước khi chỉnh sửa. Để tạo tệp sao lưu, thêm đuôi mở rộng sao lưu ngay sau tùy chọn -i:

sed -i.bak '1~2d' everyother.txt

Lệnh trên sẽ tạo một tệp sao lưu với đuôi .bak rồi mới chỉnh sửa tệp gốc tại chỗ.

Thay thế văn bản

Có lẽ mục đích sử dụng nổi tiếng nhất của sed là thay thế văn bản. Sed có thể tìm kiếm các mẫu văn bản sử dụng biểu thức chính quy, và sau đó thay thế văn bản tìm được bằng một thứ gì đó khác.

Ở dạng cơ bản nhất, bạn có thể thay đổi một từ thành từ khác bằng cú pháp sau:

's/old_word/new_word/'

Trong đó, s là lệnh thay thế. Ba dấu gạch chéo (/) dùng để phân tách các trường văn bản khác nhau. Bạn có thể dùng các ký tự khác làm dấu phân cách nếu cần thiết.

Ví dụ, nếu bạn muốn thay đổi tên một website, việc sử dụng một dấu phân cách khác sẽ hữu ích vì URL có chứa dấu gạch chéo. Thực hiện lệnh sau để in ra một URL với echo và chỉnh sửa nó bằng sed, sử dụng dấu gạch dưới (_) làm dấu phân cách:

echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'

Lệnh trên sẽ thay thế com/index bằng org/home. Kết quả in ra sẽ là URL đã được chỉnh sửa:

Output

http://www.example.org/home.ht

Đừng quên dấu phân cách cuối cùng, nếu không sed sẽ báo lỗi. Nếu bạn chạy lệnh:

echo "http://www.example.com/index.html" | sed 's_com/index_org/home'

Kết quả sẽ là:

Output

sed: -e expression #1, char 20: unterminated `s' command

Hãy tạo một tệp mới để thực hành một số thay thế. Thực hiện lệnh sau để tạo tệp văn bản có tên song.txt:

echo "this is the song that never ends
yes, it goes on and on, my friend
some people started singing it
not knowing what it was
and they'll continue singing it forever
just because..." > song.txt

Bây giờ, hãy thay thế chuỗi on bằng forward. Sử dụng lệnh:

sed 's/on/forward/' song.txt

Kết quả sẽ như sau:

Output

this is the sforwardg that never ends
yes, it goes forward and on, my friend
some people started singing it
not knowing what it was
and they'll cforwardtinue singing it forever
just because...

Những điều cần lưu ý: sed thay thế mẫu khớp, không phải toàn bộ từ. Chẳng hạn, từ “song” sẽ bị biến thành “sforwardg”. Ngoài ra, ở dòng 2, lần xuất hiện thứ hai của “on” không bị thay thế – vì mặc định lệnh s chỉ thay thế lần khớp đầu tiên trên mỗi dòng. Để thay thế tất cả các lần khớp của “on” trên mỗi dòng, bạn cần thêm tham số (flag) g vào lệnh thay thế:

sed 's/on/forward/g' song.txt

Output

this is the sforwardg that never ends
yes, it goes forward and forward, my friend
some people started singing it
not knowing what it was
and they'll cforwardtinue singing it forever
just because...

Nếu bạn chỉ muốn thay thế lần khớp thứ hai của “on” trên mỗi dòng, thay vì tham số g bạn dùng số 2:

sed 's/on/forward/2' song.txt

Kết quả là những dòng không có lần xuất hiện thứ hai của “on” sẽ không bị thay đổi:

Output

this is the song that never ends
yes, it goes on and forward, my friend
some people started singing it
not knowing what it was
and they'll continue singing it forever
just because...

Nếu bạn chỉ muốn xem những dòng có sự thay đổi, hãy dùng tùy chọn -n để ẩn việc in tự động, và truyền lệnh p vào lệnh thay thế để chỉ in ra những dòng được thay thế:

sed -n 's/on/forward/2p' song.txt

Dòng thay đổi sẽ được in ra:

Output

yes, it goes on and forward, my friend

Bạn có thể kết hợp nhiều tham số ở cuối lệnh. Nếu bạn muốn quá trình tìm kiếm không phân biệt chữ hoa chữ thường, bạn có thể thêm tham số i:

sed 's/SINGING/saying/i' song.txt

Output

this is the song that never ends
yes, it goes on and on, my friend
some people started saying it
not knowing what it was
and they'll continue saying it forever
just because...

Thay thế và tham chiếu văn bản khớp

Nếu bạn muốn tìm kiếm các mẫu phức tạp hơn với biểu thức chính quy, có nhiều cách để tham chiếu đến phần văn bản khớp được trong chuỗi thay thế.

Ví dụ, để khớp từ đầu dòng cho đến từ “at”, hãy sử dụng lệnh:

sed 's/^.*at/REPLACED/' song.txt

Output

REPLACED never ends
yes, it goes on and on, my friend
some people started singing it
REPLACED it was
and they'll continue singing it forever
just because...

Bạn sẽ nhận thấy biểu thức đại diện (.*) khớp từ đầu dòng cho đến lần xuất hiện cuối cùng của “at”.

Nếu bạn không biết chính xác chuỗi nào sẽ khớp, bạn có thể dùng ký tự & để đại diện cho phần văn bản đã khớp trong chuỗi thay thế. Hãy đặt dấu ngoặc đơn quanh phần khớp được:

sed 's/^.*at/(&)/' song.txt

Output

(this is the song that) never ends
yes, it goes on and on, my friend
some people started singing it
(not knowing what) it was
and they'll continue singing it forever
just because...

Một cách linh hoạt hơn để tham chiếu đến văn bản khớp là dùng dấu ngoặc đơn được escape (trước bằng dấu \) để nhóm các phần khớp. Mỗi nhóm được đánh số thứ tự; nhóm đầu tiên có thể được tham chiếu bằng \1, nhóm thứ hai bằng \2, v.v.

Trong ví dụ này, ta sẽ hoán đổi hai từ đầu tiên của mỗi dòng:

sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt

Output

is this the song that never ends
yes, goes it on and on, my friend
people some started singing it
knowing not what it was
they and'll continue singing it forever
because just...

Như bạn thấy, kết quả chưa hoàn hảo. Ví dụ, dòng thứ hai bỏ qua từ đầu tiên vì chứa ký tự không có trong tập ký tự được liệt kê, hoặc từ “they’ll” bị coi là hai từ. Hãy cải tiến biểu thức chính quy cho chính xác hơn:

sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt

Output

is this the song that never ends
it yes, goes on and on, my friend
people some started singing it
knowing not what it was
they'll and continue singing it forever
because... just

Kết quả này tốt hơn, vì nó nhóm cả dấu câu kèm theo từ. Chú ý rằng chúng ta lặp lại biểu thức trong dấu ngoặc đơn (một lần không có ký tự *, và một lần có nó) để đảm bảo rằng sed tìm thấy ít nhất một lần khớp trước khi áp dụng ký tự đại diện * (vì * khớp với tập ký tự đứng trước nó không hoặc nhiều lần, dẫn đến việc coi như khớp ngay cả khi không có mẫu nào).

Kết luận

Trong hướng dẫn này, bạn đã khám phá lệnh sed. Bạn đã in ra các dòng cụ thể từ tệp, tìm kiếm văn bản, xóa dòng, ghi đè tệp gốc, và sử dụng biểu thức chính quy để thay thế văn bản. Bạn sẽ nhận thấy rằng với các lệnh sed được xây dựng một cách chính xác, bạn có thể nhanh chóng biến đổi một tài liệu văn bản.

Để tối ưu hóa chi phí mà vẫn đảm bảo hiệu suất cho các tác vụ tự động hóa với sed, bạn có thể mua VPS giá rẻ từ nhà cung cấp uy tín. Sở hữu một VPS riêng giúp bạn dễ dàng triển khai và kiểm soát các script xử lý văn bản một cách hiệu quả.

Trong bài viết tiếp theo của series này, bạn sẽ khám phá một số tính năng nâng cao hơn.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *