Vài điều về các tham số đặc biệt trong Shell Script

Hello mọi người, hôm nay tôi sẽ nói về shell script trên Linux: đó là các special parameters. Mấy cái ký tự nhìn lạ lạ như $*, $@, $#, $? này thực ra là các biến có sẵn trong shell (ví dụ như Bash) và nó chứa rất nhiều thông tin hữu ích về script của mình. Nói nôm na, đây là những biến có sẵn mà shell tự cung cấp, mình không thể gán giá trị cho chúng một cách thủ công được. Cách dùng thì cứ thêm dấu $ đằng trước là được, và chúng cực kỳ bá đạo trong việc xử lý argument, debug hay quản lý process.

9eb073d1-66d6-44b7-9335-d3b20b3a61f7

Các tham số đặc biệt phổ biến

*1) `$` Tất cả đối số trong một chuỗi duy nhất**

  • Mô tả: Thằng này sẽ lấy tất cả các arguments mà mọi người truyền vào script, gom hết lại thành một string duy nhất. Các tham số sẽ được ngăn cách bởi ký tự đầu tiên trong biến IFS thường là dấu cách.
  • Dùng khi nào? Hữu ích khi mọi người muốn xử lý tất cả các argument như một khối thống nhất.
  • Ví dụ:
    #!/bin/bash
    echo "Tất cả argument trong một chuỗi: $*"

    Nếu mọi người chạy script ./script.sh arg1 arg2 arg3, kết quả sẽ là: Tất cả argument trong một chuỗi: arg1 arg2 arg3

2) $@ Tất cả đối số, mỗi đứa một chuỗi riêng

  • Mô tả: Thằng này cũng đại diện cho tất cả các tham số, nhưng mỗi tham số được coi là một chuỗi riêng biệt. Đây là điểm khác biệt chí mạng so với $*.
  • Dùng khi nào? Đây là lựa chọn hàng đầu khi mọi người cần duyệt qua từng argument, đặc biệt là khi các argument có chứa dấu cách.
  • Ví dụ:
    #!/bin/bash
    for arg in "$@"; do
        echo "Argument: $arg"
    done

    Chạy ./script.sh "arg1 có cách" arg2 arg3 sẽ cho ra:

    Argument: arg1 có cách
    Argument: arg2
    Argument: arg3

3) $# Số lượng đối số

  • Mô tả: Chứa số lượng argument đã được truyền vào script.
  • Dùng khi nào? Cực kỳ hữu ích để kiểm tra xem người dùng có nhập đủ số lượng argument mà script yêu cầu hay không.
  • Ví dụ:
    #!/bin/bash
    echo "Số lượng argument: $#"
    if [ $# -lt 2 ]; then
      echo "Lỗi: Cần ít nhất 2 argument"
      exit 1
    fi

    Chạy ./script.sh arg1 sẽ báo lỗi:

    Số lượng argument: 1
    Lỗi: Cần ít nhất 2 argument

4) $? Exit Status của lệnh cuối cùng

  • Mô tả: Đây là status của lệnh vừa chạy xong. Nó lưu lại exit status của lệnh đó. Nếu bằng 0 là success, khác 0 là fail.
  • Dùng khi nào? Dùng để check lỗi và flow control của script. Bắt buộc phải dùng trong các script quan trọng.
  • Ví dụ:
    #!/bin/bash
    ls /nonexistent
    echo "Exit status của lệnh ls: $?"

    Kết quả:

    ls: cannot access '/nonexistent': No such file or directory
    Exit status của lệnh ls: 2

5) $$ Process ID của script hiện tại

  • Mô tả: Giữ process ID (PID) của chính cái script đang chạy.
  • Dùng khi nào? Rất tiện để ghi log, tạo file tạm với tên duy nhất để tránh bị ghi đè, hoặc theo dõi tiến trình của script.
  • Ví dụ:
    #!/bin/bash
    echo "Process ID của tôi là: $$"

    Kết quả: Process ID của tôi là: 12345 (số này sẽ thay đổi mỗi lần chạy)

6) $! Process ID của lệnh chạy ngầm cuối cùng

  • Mô tả: Lưu lại PID của cái lệnh gần nhất được chạy ở chế độ background dùng dấu & ở cuối.
  • Dùng khi nào? Để quản lý và theo dõi các background process.
  • Ví dụ:
    #!/bin/bash
    sleep 10 &
    echo "Process ID của lệnh chạy ngầm: $!"

    Kết quả: Process ID của lệnh chạy ngầm: 67890

7) $0 Tên của script

  • Mô tả: Chứa tên của file script đang được thực thi.
  • Dùng khi nào? Hay dùng để hiển thị usage message.
  • Ví dụ:
    #!/bin/bash
    echo "Tên script: $0"

    Chạy ./script.sh sẽ ra: Tên script: ./script.sh

8) $1, $2, …, $n Các đối số riêng lẻ

  • Mô tả: Đại diện cho argument thứ 1, thứ 2, và cứ thế tiếp tục.
  • Dùng khi nào? Để truy cập trực tiếp vào một argument cụ thể.
  • Ví dụ:
    #!/bin/bash
    echo "Argument đầu tiên: $1"
    echo "Argument thứ hai: $2"

    Chạy ./script.sh foo bar sẽ ra:

    Argument đầu tiên: foo
    Argument thứ hai: bar

9) $- Các tùy chọn hiện tại của shell

  • Mô tả: Chứa các options đang được bật cho shell hiện tại.
  • Dùng khi nào? Hữu ích để debug hoặc kiểm tra cấu hình của shell.
  • Ví dụ:
    #!/bin/bash
    echo "Các option của shell: $-"

    Kết quả ví dụ: Các option của shell: hB

10) $_ Argument cuối cùng của lệnh trước đó

  • Mô tả: Giữ lại argument cuối cùng của lệnh vừa mới thực thi xong.
  • Dùng khi nào? Khá tiện khi dùng trong terminal tương tác, muốn dùng lại argument cuối.
  • Ví dụ:
    #!/bin/bash
    echo "hello world"
    echo "Argument cuối cùng: $_"

    Kết quả:

    hello world
    Argument cuối cùng: world

Sự khác biệt giữa $*$@

Có thể mọi người sẽ bị nhầm những chỗ như sau:

  • $*: Gom tất cả argument vào một chuỗi duy nhất. Nếu argument có dấu cách, nó sẽ gây ra lỗi.
  • $@: Giữ nguyên từng argument thành các chuỗi riêng biệt. An toàn hơn rất nhiều khi sử dụng for.

Xem ví dụ:

#!/bin/bash
echo "--- Dùng \$* ---"
for arg in $*; do
  echo "Từ \$*: $arg"
done

echo "--- Dùng \"\$@\" ---"
for arg in "$@"; do
  echo "Từ \$@: $arg"
done

Chạy với lệnh ./script.sh "arg 1" arg2:

--- Dùng $* ---
Từ $*: arg
Từ $*: 1
Từ $*: arg2
--- Dùng "$@" ---
Từ $@: arg 1
Từ $@: arg2

$* đã “phá” cái chuỗi "arg 1" của chúng ta ra thành 2 phần. Trong khi đó, "$@" dùng trong cặp nháy kép vẫn giữ nguyên nó là một argument duy nhất. Đây là lý do 99% trường hợp mọi người nên dùng "$@" để đảm bảo an toàn.

Tips

  • Kiểm tra argument: Dùng $# để check xem người dùng đã nhập đủ số lượng argument chưa trước khi chạy logic chính.
  • Xử lý dấu cách an toàn: Luôn ưu tiên dùng "$@" thay vì $* khi duyệt qua các argument để tránh lỗi vặt với những argument chứa dấu cách.
  • Kiểm tra lỗi: Luôn kiểm tra $? sau những lệnh quan trọng (copy file, xóa file, gọi API…) để xử lý lỗi kịp thời.
  • Dùng file tạm: Kết hợp $$ với tên file tạm (ví dụ /tmp/script_$$ .log) để đảm bảo mỗi lần chạy script sẽ tạo ra một file riêng, không bị xung đột.
  • Debug: Dùng $0, $# để ghi log, giúp quá trình tìm lỗi dễ dàng hơn.

Thông tin nổi bật

Báo cáo quan trọng

Chia sẻ bài viết:
Theo dõi
Thông báo của
0 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Phản hồi nội tuyến
Xem tất cả bình luận