Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình Bash

Thành thạo Bash printf: Ví dụ thực tế & Định dạng nâng cao

Bài viết này sẽ chỉ cho bạn một số ví dụ thực tế dùng lệnh printf trong Bash/Shell trên Linux.

Lệnh printf xuất văn bản giống như lệnh echo – nhưng cho phép kiểm soát nhiều hơn định dạng output.

Đây là công cụ hữu ích để tạo output văn bản định dạng riêng – đặc biệt nếu cần nhúng biến trong văn bản, bao gồm xuống dòng, căn chỉnh và định dạng văn bản, thậm chí hiển thị giá trị chuyển đổi.

Cú pháp printf

Lệnh printf có cú pháp sau:

printf [-v var] format [arguments]...

Lưu ý:

  • Tùy chọn -v bảo printf lưu kết quả vào biến var thay vì in ra
  • format là chuỗi chứa tổ hợp ba giá trị khác nhau:
    • Ký tự bình thường sẽ in nguyên văn
    • Ký tự thoát backslash được diễn giải trước khi in
    • Chuyển đổi được chỉ định và thay thế bằng đối số tương ứng (hãy nghĩ chúng giống như biến)
  • arguments sẽ truyền cho format và dùng trong các chuyển đổi được định nghĩa
    • Nếu đối số nhiều hơn specifier chuyển đổi trong format, chuỗi format lặp lại cho đến khi hết arguments
    • Nếu đối số ít hơn, specifier số được đặt về 0, và specifier chuỗi được đặt về null

Ký tự thoát, Chuyển đổi, và Flag của printf

printf có bộ sưu tập khổng lồ các tùy chọn có thể truyền để định dạng văn bản theo nhiều cách. Các ví dụ dưới sẽ chỉ một số ứng dụng thực tế.

Thay vì liệt kê tất cả tùy chọn có thể truyền cho lệnh ở đây, bạn có thể xem manual đầy đủ cho lệnh printf trên hệ thống bằng:

man printf

Ví dụ printf Bash/Shell

Đúng, tất cả những thứ đó thực sự dùng để làm gì?

Hiển thị giá trị làm tròn của số

Trước hết, một tình huống đơn giản – bạn muốn định dạng số thành hai chữ số thập phân để hiển thị:

printf "%.2f" 4.21423557

Điều này sẽ xuất:

4.21

Định dạng chỉ định %.2f bảo printf định dạng số thành hai chữ số thập phân. Điều này dùng chỉ thị độ chính xác, là dấu . (chấm) trong định dạng.

Điều này sẽ làm tròn số thay vì cắt ngắn nó đến số chữ số thập phân cho trước. Làm tròn số thực là kỳ lạ – nên kiểm tra output của bạn!

Sự kỳ lạ của làm tròn

Để minh họa sự kỳ lạ này, xem xét sau:

printf "%.2f" 4.215

Nên là 4.22, phải không? Sai. Trong triển khai printf của zsh, nó sẽ làm tròn thành:

4.21

Để xác nhận số đang được làm tròn, ta kiểm tra giá trị khác:

printf "%.2f" 4.216

Sẽ trả về:

4.22

… vậy số truyền cho printf đang được làm tròn.

Tại sao giá trị làm tròn của 4.215 lại có vẻ sai? Đơn giản, vì là số thực dấu phẩy động, sự không chính xác do sự chênh lệch giữa giá trị hiển thị và giá trị máy tính dùng trong tính toán.

Có cách khắc phục, nhưng ngoài phạm vi bài này – sẽ đề cập bài khác.

Chuyển đổi giá trị (Thập phân, Thập lục phân, Bát phân)

Tình huống phổ biến – bạn muốn hiển thị số ở định dạng khác với cách chúng được cung cấp bởi chương trình hoặc script khác. printf có thể làm này dùng cú pháp specifier chuyển đổi:

printf "Decimal: %d\nHexadecimal: %x\nOctal: %o\n" 64 64 64

Điều này sẽ xuất:

Decimal: 64
Hexadecimal: 40
Octal: 100

Số 64 được truyền cho formatter 3 lần và hiển thị ở ba định dạng khác nhau.

Tạo output đẹp mắt

Ví dụ dưới xuất bảng định dạng dùng printf – tôi sẽ giải thích trong comment để rõ ràng:

#!/bin/bash
# Định nghĩa định dạng cho text header
# Đây là dòng mới (\n) theo sau chuỗi căn trái 15 ký tự (%-15s), theo sau chuỗi 15 ký tự (%15s), cuối cùng chuỗi 10 ký tự (%10s) và newline khác
header_format="\n %-15s %15s %10s\n"
# Định nghĩa định dạng cho dữ liệu mỗi hàng
# Hai mục đầu giống header, nhưng mục cuối khác - số thực 2 chữ số thập phân (%11.2f)
row_format=" %-15s %15s %11.2f\n"
# Dùng printf in header
# Định dạng được chỉ định, và đối số chứa tên cột bảng được cung cấp
# printf sẽ lấy header_format, chèn giá trị từ thuộc tính vào, định dạng theo spec, rồi in
printf "$header_format" "CAR BRAND" "COLOUR" "TOP SPEED"
# In đường kẻ ngang dưới header bảng
# Ở đây, printf dùng in dấu bằng. Mở rộng ngoặc nhọn (brace expansion) là shortcut script shell chạy printf cho mọi số từ 1 đến 50, lặp ký hiệu 50 lần tạo đường kẻ
printf '=%.0s' {1..50}
# In từng hàng dữ liệu dùng row_format. Mỗi dòng (chỉ thị bằng backslash và xuống dòng) chứa ba giá trị - hãng xe, màu, tốc độ tối đa
# Giá trị nào có dấu cách cần đặt trong ngoặc kép vì giá trị tách bằng dấu cách và printf không biết đâu kết thúc đâu bắt đầu
printf "$row_format" \
  Toyota Blue 100 \
  Ford "Light Green" 78.3875 \
  "General Motors" Purple 15.96

Chạy script này sẽ xuất:

CAR BRAND COLOUR TOP SPEED
==================================================
Toyota Blue 100.00
Ford Light Green 78.39
General Motors Purple 15.96

Nhìn kỹ cách dữ liệu được định dạng bởi printf ở đây. Nơi chuỗi độ dài ký tự cụ thể được chỉ định cho header và hàng, văn bản căn chỉnh. Tốc độ tối đa được định dạng hai chữ số thập phân và đặt đúng vị trí. Văn bản căn phải trừ nơi chỉ định cho cột đầu.

Với lượng cú pháp nhỏ, dữ liệu khó đọc đã biến thành thông tin hữu ích.

Giới hạn là trời

Bạn sẽ tự nghĩ ra lý do dùng printf – xây dựng giao diện dòng lệnh với menu đẹp cho script, bảng kết quả truy vấn database – đây là công cụ mạnh để có trong túi, đặc biệt nếu muốn gây ấn tượng với script shell trông chuyên nghiệp thay vì chỉ đổ text không định dạng ra màn hình.

Bạn có thể kết hợp printf với các lệnh xử lý văn bản khác trong Linux.