Làm thế nào tôi có thể phát hiện ra rằng không có tùy chọn nào được thông qua với getopts?


19

Tôi có mã này -

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
done
print 'hi'$name

Khi tôi chạy bash getoptDemos.sh(không có tùy chọn), nó sẽ in hithay vì gọi hàm usage. Nó gọi việc sử dụng khi các tùy chọn khác ngoài w, h và l được đưa ra. Sau đó, nó không thể hoạt động khi không có tùy chọn được chỉ định.

Tôi đã cố gắng sử dụng ?, \?, :thay cho *nhưng tôi không thể đạt được những gì tôi muốn. Tôi có nghĩa là tất cả docstrên getoptnói nó để sử dụng ?.

Tôi đang làm gì sai?


Bạn đang chạy nó dưới cái vỏ nào?
Julian

Tôi đang điều hành nó dưới/bin/bash
Hussain Tamboli

Các lựa chọn thay thế khác: wiki.bash-hackers.org/howto/getopts_tutorial
slm

Câu trả lời:


15

Khi bạn chạy tập lệnh này mà không có bất kỳ tùy chọn nào, getopt sẽ trả về false, vì vậy nó sẽ không nhập vào vòng lặp. Nó sẽ chỉ rơi xuống bản in - đây có phải là ksh / zsh không?

Nếu bạn phải có một tùy chọn, cách tốt nhất của bạn là kiểm tra tên $ sau vòng lặp.

if [ -z "$name" ]
then
   usage
   exit
fi

Nhưng hãy chắc chắn $namelà trống trước khi gọi getopts(vì có thể có một $namemôi trường mà shell nhận được khi khởi động) với

unset name

(trước getoptsvòng lặp)


Không. bash của nó. Vậy làm thế nào để tôi đạt được những gì tôi muốn - xử lý no argumenttình trạng bằng cách sử dụng bash.
Hussain Tamboli

Nếu bạn muốn một tùy chọn bắt buộc, tôi không nghĩ rằng điều đó là có thể - đó có thể là lý do tại sao chúng được gọi là tùy chọn :) Bạn có thể kiểm tra tên $ mặc dù, sau vòng lặp để đảm bảo rằng nó đã được đặt. nếu [-z "$ name"]; sau đó sử dụng; lối thoát hiểm ; fi
Julian

cảm ơn. các mã trên thực sự có ích. Nó quá tệ getoptskhông có điều khoản như vậy. Điều tồi tệ hơn thế là không thể nâng cao bạn.
Hussain Tamboli

Nếu tôi đang chạy shell khác thì sao? zsh, sh. Có vỏ nào khác ngoài bash chăm sóc tình trạng này không?
Hussain Tamboli

20

getoptsxử lý các tùy chọn lần lượt. Đó là công việc của nó. Nếu người dùng không có tùy chọn nào, lệnh đầu tiên getoptsthoát khỏi vòng lặp while.

Nếu không có tùy chọn nào đưa ra một đối số, giá trị OPTINDcho biết có bao nhiêu tùy chọn được thông qua. Nói chung, OPTINDlà số lượng đối số là tùy chọn hoặc đối số cho tùy chọn, trái ngược với đối số không phải tùy chọn (toán hạng).

while getopts …; do …; done
if [ $OPTIND -eq 1 ]; then echo "No options were passed"; fi
shift $((OPTIND-1))
echo "$# non-option arguments"

Trong mọi trường hợp, bạn không cố gắng xác định liệu không có tùy chọn nào, nhưng liệu không có nametùy chọn cài đặt nào được thông qua. Vì vậy, kiểm tra nếu namekhông được đặt (và hãy cẩn thận để bỏ đặt nó trước) .


1
cảm ơn. +1 cho bạn. khi tôi đặt 3 dòng cuối cùng từ mã của bạn vào sample.sh và chạy bash sample.sh -abc file.txtnó sẽ cho - 1 non-option arguments. Làm thế nào để tôi tìm ra có bao nhiêu lựa chọn đã được đưa ra. (ở đây 3)
Hussain Tamboli

1
Lạ là không có ai bình luận về lỗi nhỏ này - nếu không có tùy chọn nào được đưa ra, thì OPTIND sẽ là 1 sau đó 'trong khi vòng lặp getopts ...'. Do đó, kiểm tra if nên kiểm tra đẳng thức với 1, không phải bằng không.
Daniel

4

Nếu tập lệnh của bạn phải nhận đối số tùy chọn là bất kỳ trường hợp nào, hãy đặt khối này vào đầu (trước khi có được).

if [[ ! $@ =~ ^\-.+ ]]
then
  #display_help;
fi

Chặn kiểm tra chuỗi tham số không bắt đầu bằng -ký hiệu, điều cho biết tham số đầu tiên không phải là đối số tùy chọn.


2

Tôi sẽ kiểm tra nó với một biến. Nếu getopts không bao giờ vượt qua vòng lặp trong trường hợp không có đối số, bạn có thể sử dụng ví dụ như thế này:

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}

no_args="true"
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
    no_args="false"
done

[[ "$no_args" == "true" ]] && { usage; exit 1; }

print 'hi'$name

0

Ngay trước getoptskhối của bạn , hãy kiểm tra xem liệu $1(đối số / tùy chọn đầu tiên bạn truyền trên dòng lệnh) có bằng một chuỗi trống không. Nếu có, hãy in thông báo sử dụng và thoát, (hoặc thực hiện một số chức năng "không có tùy chọn" nếu bạn là người vô chính phủ), nếu không hãy getoptsphân tích các tùy chọn như bình thường.

Lý do tính năng này không được bao gồm trong getopts, là bởi vì bạn đã có thể hoàn thành nó trong bash với "if-other". Thí dụ:

if [[ $1 == "" ]]; then
    Your_Usage_Function;
    exit;
else
   #parse options with getopts code block here;
fi

Có lý?

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.