Cung cấp hai đối số cho một tùy chọn bằng cách sử dụng getopts


10

Trong đoạn mã dưới đây khi tôi đưa ra tùy chọn rthì getoptsyêu cầu một đối số:

while getopts ":hr::l:" opt; do
    case $opt in
        r ) echo "Run Numbers - argument = $OPTARG " ;;
        l ) echo "Latency range - argument = $OPTARG" ;;
        h ) helptext
            graceful_exit ;;
        * ) usage
            clean_up
            exit 1
    esac
done

Nhưng tôi cần phải vượt qua hai đối số sau -rtùy chọn, thay vì một. Có cách nào làm dễ hơn không?

Câu trả lời:


20

Bạn không thể vượt qua hai đối số với tùy chọn duy nhất bằng cách sử dụng getopts.

Tôi đề nghị các phương án sau:

  1. Đặt dấu ngoặc kép xung quanh nhiều đối số

    Trong trường hợp này, getopts sẽ coi chúng là một đối số, nhưng bạn sẽ có thể phân tách nó sau này. Bạn thậm chí có thể đặt tất cả các đối số trong mảng cùng một lúc:

    #!/bin/bash  
    
    while getopts ":hr:l:" opt; do
        case $opt in
            r ) echo "Run Numbers - argument = $OPTARG "
                set -f # disable glob
                IFS=' ' # split on space characters
                array=($OPTARG) ;; # use the split+glob operator
            l ) echo "Latency range - argument = $OPTARG" ;;
            h ) helptext
                graceful_exit ;;
            * ) usage
                clean_up
                exit 1
        esac
    done
    
    echo "Number of arguments: ${#array[@]}"
    echo -n "Arguments are:"
    for i in "${array[@]}"; do
      echo -n " ${i},"
    done
    printf "\b \n"

    Ví dụ về chạy:

    ./script -r "123 456 789"

    Và đầu ra:

    Run Numbers - argument = 123 456 789 
    Number of arguments: 3
    Arguments are: 123, 456, 789
  2. Sử dụng dấu phẩy (hoặc ký tự ưa thích khác) làm dấu phân cách

    ./script -r 123,456,789

    và bạn chỉ cần thay thế IFS=" "bằng IFS=,trong mã ở trên. Điều đó có lợi thế cho phép các yếu tố trống. Như đã chỉ ra trong phần bình luận, giải pháp này được lựa chọn bởi một số chương trình phổ biến, vd lsblk -o NAME,FSTYPE,SIZE.

  3. Cho phép nhiều -rtùy chọn

    Nhiều -r, nhưng mỗi chỉ lấy một đối số:

    ./script -r 123 -r 456 -r 789

    Sau đó, các đối số sẽ được thêm vào từng mảng một

    array+=("$OPTARG")

    Điều đó có một ưu điểm là không có giới hạn về các ký tự mà các yếu tố có thể chứa. Công cụ này cũng được sử dụng bởi một số công cụ linux tiêu chuẩn, vd awk -v var1=x -v var2=y.


3
Ý tưởng dấu phân cách dấu phẩy là tốt, vì nó được sử dụng bởi các lệnh tiêu chuẩn khác nhau, đáng chú ý mount.
PM 2Ring

Có thể, người ta vẫn có thể chuyển đổi biểu mẫu "phân cách" này thành mảng với array=(${OPTARG//,/ }). Tuy nhiên, một khả năng khác là chỉ sử dụng nhiều lần -r argtùy chọn mỗi lần thêm phần tử vào một mảng array+=($OPTARG).
jimmij

Thậm chí dễ dàng hơn:IFS=',' array=($OPTARG)
PM 2Ring

Ví dụ: pgrepsử dụng dấu phẩy : ps -s 123,456 ..., grep sử dụng lặp lại tùy chọn: grep -e pattern1 -e pattern2 ...( -elà tùy chọn khi chỉ sử dụng một mẫu).
Volker Siegel

2
bạn không muốn làm cho người dùng làm nhiều việc hơn, ví dụ như đặt dấu ngoặc kép trong danh sách, chỉ vì giới hạn trong ngôn ngữ / thư viện bạn đang sử dụng. Tuy nhiên việc sử dụng ,có vẻ hợp lý, thậm chí tốt hơn so với việc sử dụng một không gian.
ctrl-alt-delor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.