Câu 1Trong printf '%s\t%s\n' a b, \t và \n đại diện cho cái gì?
Đầu ra và báo cáo — Ghi bằng printf và here-doc
Bài viết này là một phần của Khóa học Linux, giúp bạn thành thạo từ đầu những kỹ năng Linux thực tiễn, từ các lệnh cơ bản đến lập trình shell script.
Canh cột bằng printf '%s\t%s\n', nối thêm kết quả bằng > và >>, tách lỗi sang tệp khác bằng 2>, rồi nhúng $(wc -l) vào mẫu here-doc để dựng một báo cáo tổng hợp — minh họa và thực hành trên terminal.
In có định dạng — printf và điều hướng nơi đầu ra đi tới
Để in kết quả của script cho dễ đọc, bạn dùng echo khi cần in một chuỗi nguyên văn, và printf khi cần chỉ định định dạng để canh đều độ rộng và dấu phân cách.
Nếu bạn chỉ cần in giá trị của một biến trên một dòng thì echo "$v" là đủ.
Viết printf '%s\t%s\n' name age thì các tham số lần lượt đi vào các chỗ %s, \t thành tab còn \n thành xuống dòng.
Khác với echo, printf không tự xuống dòng, nên hãy luôn viết \n ở cuối dòng.
Đầu ra của một lệnh đi theo hai luồng: đầu ra chuẩn và lỗi chuẩn.
> file ghi đè tệp bằng đầu ra chuẩn, >> file nối thêm vào cuối, còn 2> file chỉ đưa lỗi chuẩn sang một tệp riêng.
Đưa kết quả bình thường vào báo cáo và lỗi sang tệp riêng thì sau này bạn truy ra nguyên nhân dễ hơn hẳn.
vi fmt.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# printf '%s\t%s\n' name age # tiêu đề phân tách bằng tab
# printf '%s\t%s\n' alice 30 # dòng dữ liệu, đã canh cột
# echo "done" >> fmt.log # nối thêm vào log
chmod +x fmt.sh
./fmt.sh
> (ghi đè) hoặc >> (nối thêm), còn lỗi được tách sang một tệp khác bằng 2>.| Cú pháp | Ý nghĩa | Ví dụ |
|---|---|---|
echo "$v" | In một biến hay chuỗi nguyên văn | echo "$name" |
printf "%s\t%s\n" a b | In có định dạng (phân tách bằng tab, xuống dòng ghi rõ) | printf '%s\t%s\n' name age |
> f | Ghi đè tệp bằng đầu ra chuẩn | echo line > report.txt |
>> f | Nối thêm đầu ra chuẩn vào một tệp | echo more >> report.txt |
2> err | Chỉ tách lỗi chuẩn sang một tệp khác | cat missing 2> err.log |
Gom báo cáo tổng hợp vào một tệp — here-doc và thay thế lệnh
Với báo cáo có bố cục cố định, hãy viết khuôn mẫu bằng here-doc và nhúng kết quả của lệnh vào bên trong nó.
Các dòng bạn viết giữa cat > report.txt <<EOF … EOF trở thành nội dung tệp nguyên văn, còn chỗ bạn viết $(...) thì kết quả chạy sẽ được mở rộng ngay tại đó.
<<EOF không có nháy sẽ mở rộng biến và thay thế lệnh, còn <<'EOF' (có nháy đơn) không mở rộng gì cả và in nguyên văn.
Các giá trị tổng hợp như số đếm hay tổng thì lấy vào biến bằng thay thế lệnh $(wc -l …) hay $(grep -c …).
Viết xong báo cáo, hãy dùng mã thoát exit để báo cho phía gọi script có chạy thành công hay không.
exit 0 nghĩa là thành công còn exit 1 nghĩa là có gì đó không ổn, và một && phía sau hay một job CI đều dựa vào đó mà quyết định.
vi summary.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# log=access.log
# lines=$(wc -l < "$log") # đếm số dòng
# cat > summary.txt <<REPORT # nhúng giá trị vào mẫu
# --- access summary ---
# total lines: $lines
# REPORT
# echo "summary.txt created"
# exit 0
chmod +x summary.sh
$(wc -l) đếm được sẽ được nhúng vào đúng chỗ $(...) trong mẫu here-doc, gom cả báo cáo vào một tệp.| Cú pháp | Ý nghĩa | Ví dụ |
|---|---|---|
<<EOF … EOF | here-doc có mở rộng biến và thay thế lệnh | cat <<EOF > t.txt |
<<'EOF' … EOF | here-doc không mở rộng gì cả, in nguyên văn | cat <<'EOF' > t.txt |
$(wc -l < f) | Lấy một giá trị tổng hợp vào biến bằng thay thế lệnh | n=$(wc -l < access.log) |
exit 0 / exit 1 | Trả về mã thoát thành công hay thất bại | exit 0 |
Tách đầu ra chuẩn và lỗi sang hai tệp riêng
Khi một lệnh duy nhất vừa cho kết quả bình thường vừa cho lỗi cùng lúc, viết > ok.txt 2> err.txt thì đầu ra chuẩn được lưu vào ok.txt còn lỗi chuẩn vào err.txt.
Vì sau đó bạn xem được "kết quả" và "vấn đề" tách bạch, dạng này rất hay dùng khi thiết kế log cho script vận hành.
ls /etc /no_such_dir > ok.txt 2> err.txt # danh sách vào ok.txt, lỗi vào err.txt
cat ok.txt # danh sách /etc (đầu ra chuẩn)
cat err.txt # lỗi /no_such_dir (lỗi chuẩn)
> ok.txt còn lỗi chuẩn vào 2> err.txt, lưu riêng cùng lúc.| Cú pháp | Ý nghĩa | Ví dụ |
|---|---|---|
cmd > ok 2> err | Đưa đầu ra chuẩn và lỗi chuẩn sang hai tệp riêng cùng lúc | ls /etc > ok.txt 2> err.txt |
echo "…" 1>&2 | Đưa một thông báo sang phía lỗi chuẩn | echo failed 1>&2 |
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Cách viết nào chỉ điều hướng lỗi chuẩn của một lệnh sang một tệp riêng?
Câu 3Khi muốn nhúng kết quả chạy của $(...) bên trong mẫu here-doc, bạn chọn thẻ mở nào?