Bài viết này sẽ chỉ cho bạn cách dùng Heredoc (Here Document) trong script Bash/Shell để làm việc với văn bản nhiều dòng.
Heredoc hữu ích nhất cho việc nhận input nhiều dòng – người dùng có thể nhập một dòng, nhấn enter, nhập dòng tiếp theo, và cứ thế. Nó cũng có thể dùng để định nghĩa văn bản nhiều dòng trong script.
Nó cũng có thể gửi nhiều lệnh vào chương trình tương tác – sẽ được minh họa trong ví dụ sau.
Các ví dụ trong bài này hoạt động cả trong Bash và Zsh Shell.
Standard Input, Piping, và Redirection
Heredoc thường dùng với Standard Input/Output và redirection/piping để gửi văn bản nhiều dòng đến các lệnh khác để xử lý, định dạng, hoặc hiển thị. Chủ đề này thực sự cần một bài riêng để giải thích khái niệm, nên đây là:
Chuyển hướng stdin, stdout, stderr trong Linux/Bash, Với Ví dụ
Các ví dụ dưới sẽ dùng khái niệm và phương pháp từ bài trên ở một số điểm.
Cú pháp Heredoc Bash/Zsh
Để bắt đầu một Heredoc, bạn chỉ cần dùng lệnh <<. Đây là dạng chuyển hướng Input/Output như nêu trên.
Cú pháp dùng Heredoc như sau:
COMMAND <<LIMITSTRING text line 1 text line 2 ... LIMITSTRING
Lưu ý:
- COMMAND có thể là bất kỳ lệnh hoặc script Linux nào – nội dung văn bản trong heredoc sẽ được gửi đến nó dùng redirection
- << Định nghĩa bắt đầu câu lệnh Heredoc
- Nếu bạn sẽ thụt lề văn bản nhiều dòng, dùng <<- (chú ý dấu gạch thêm) thay thế – nó sẽ bỏ tab đầu mỗi dòng
- LIMITSTRING là chuỗi phải gõ để kết thúc nhập văn bản cho Heredoc
- Vì Heredoc là nhiều dòng, với người dùng nhấn ENTER để xuống dòng, bạn không thể nhấn enter để dừng nhập văn bản mới.
- LIMITSTRING, khi xuất hiện, báo cho Heredoc bạn đã nhập xong và kết thúc
- Nó có thể là bất cứ thứ gì – hãy chắc chắn dùng chuỗi ký tự不会出现在你的文本中,以免过早结束。
- Thực hành phổ biến là dùng văn bản EOF (viết tắt của End Of File) làm LIMITSTRING – miễn là văn bản này không xuất hiện bên trong Heredoc.
- Bạn có thể có bao nhiêu dòng văn bản tùy thích
Ví dụ Heredoc
Chấp nhận input văn bản nhiều dòng
Ví dụ này sẽ chấp nhận nhiều dòng văn bản và gửi đến lệnh cat để hiển thị:
cat <<EOF This is line 1 This is line 2 EOF
Ví dụ trên nên được gõ vào chương trình terminal của bạn.
Sử dụng biến
Bạn có thể dùng biến shell trong Heredoc:
cat <<EOF This is line 1 This is line 2 Your current directory is $PWD EOF
Trên đây, biến $PWD được hiển thị trong một dòng của Heredoc – biến này giữ giá trị thư mục làm việc hiện tại.
Chuyển hướng output của Heredoc
Chuyển hướng tiêu chuẩn (xem trước trong bài nếu bạn không biết khái niệm này) có thể dùng để gửi nội dung Heredoc sau khi đã gửi đến COMMAND đến chương trình hoặc file khác:
cat <<EOF > output.txt This is line 1 This is line 2 Your current directory is $PWD EOF
Trên đây, cat đọc nội dung Heredoc, và output của cat được chuyển hướng và ghi vào file output.txt dùng lệnh >.
Định nghĩa văn bản nhiều dòng trong script
Bạn có thể dùng Heredoc trong script. Vì shell script chỉ là danh sách các lệnh theo dòng để feed vào shell, nó sẽ hoạt động giống nhau.
Thú vị là có thể thụt lề code script – nếu bạn không muốn tab đó xuất hiện trong văn bản, bạn có thể thêm – (dash) vào khai báo Heredoc để bỏ khoảng trắng đầu mỗi dòng:
#!/bin/bash
if $trueOrFalse; then
cat <<-EOF > output.txt
This is line 1
This is line 2
Your current directory is $PWD
EOF
fi
Gán Heredoc cho biến
Bạn có thể gán văn bản nhiều dòng trong Heredoc cho biến script bằng cách đọc nó với lệnh cat và gán output cho biến như sau:
mytext=$(cat <<-EOF This is line 1 This is line 2 Your current directory is $PWD EOF ) echo $mytext
Gửi nhiều lệnh đến chương trình tương tác
Heredoc cũng có thể gửi nhiều dòng văn bản đến chương trình tương tác. Một số chương trình, sau khi chạy, mong đợi bạn gõ lệnh riêng – chúng có thể chấp nhận văn bản để xử lý hoặc cung cấp shell riêng để phát lệnh.
Ví dụ điển hình là MySQL – sau khi MySQL chạy và kết nối đến server, bạn có thể gõ lệnh riêng theo sau enter để truy vấn dữ liệu. Bằng Heredoc, bạn có thể viết sẵn các lệnh này và gửi vào MySQL mà không cần tương tác người dùng:
mysql -uUSERNAME -pPASSWORD DATABASE <<EOF SHOW TABLES; SELECT * FROM posts; EOF
Trên đây, lệnh MySQL dùng để kết nối đến DATABASE cho trước với USERNAME và PASSWORD.
Hai lệnh tuần tự sẽ được chạy khi kết nối sẵn sàng – một để SHOW TABLES và một để SELECT tất cả bản ghi từ bảng posts.