Có một số công cụ tích hợp sẽ nhận ra -x
và --xxxx
là các công tắc, và không phải là đối số, hoặc bạn có phải trải qua tất cả các biến đầu vào, kiểm tra dấu gạch ngang và sau đó phân tích các đối số sau đó không?
Có một số công cụ tích hợp sẽ nhận ra -x
và --xxxx
là các công tắc, và không phải là đối số, hoặc bạn có phải trải qua tất cả các biến đầu vào, kiểm tra dấu gạch ngang và sau đó phân tích các đối số sau đó không?
Câu trả lời:
Sử dụng getopts
.
Nó khá di động vì nó nằm trong thông số POSIX. Thật không may, nó không hỗ trợ các tùy chọn dài.
Xem thêm getopts
hướng dẫn này với sự giúp đỡ của wiki bash-hacker và câu hỏi này từ stackoverflow.
Nếu bạn chỉ cần các tùy chọn ngắn, mẫu sử dụng thông thường cho getopts
(sử dụng báo cáo lỗi không im lặng) là:
# process arguments "$1", "$2", ... (i.e. "$@")
while getopts "ab:" opt; do
case $opt in
a) aflag=true ;; # Handle -a
b) barg=$OPTARG ;; # Handle -b argument
\?) ;; # Handle error: unknown option or missing required argument.
esac
done
while getopts "ab:" opt
làm gì?
:
sau tùy chọn biểu thị nó yêu cầu một đối số. A :
là ký tự đầu tiên có nghĩa là để chặn các thông báo lỗi.
Tôi giả sử bạn đang sử dụng bash hoặc tương tự. Một ví dụ:
all=false
long=false
while getopts ":hal" option; do
case $option in
h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;;
a) all=true ;;
l) long=true ;;
?) echo "error: option -$OPTARG is not implemented"; exit ;;
esac
done
# remove the options from the positional parameters
shift $(( OPTIND - 1 ))
ls_opts=()
$all && ls_opts+=( -a )
$long && ls_opts+=( -l )
# now, do it
ls "${ls_opts[@]}" "$@"
+=
với một mảng. Không biết bạn có thể làm điều đó. Đẹp!
Bạn phải viết một chu kỳ để phân tích các tham số. Thật vậy, bạn có thể sử dụng getopts
lệnh để làm điều đó một cách dễ dàng.
Đây là một ví dụ đơn giản từ getopts
trang hướng dẫn:
aflag=
bflag=
while getopts ab: name
do
case $name in
a) aflag=1;;
b) bflag=1
bval="$OPTARG";;
?) printf "Usage: %s: [-a] [-b value] args\n" $0
exit 2;;
esac
done
if [ ! -z "$aflag" ]; then
printf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; then
printf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"
Gần đây tôi đã viết một kịch bản cho công việc linh hoạt và được phép cho nhiều loại công tắc theo bất kỳ thứ tự nào. Tôi không thể tiết lộ kịch bản đầy đủ vì lý do pháp lý rõ ràng (không đề cập đến việc tôi không có nó với tôi vào lúc này), nhưng đây là phần thịt của nó .. bạn có thể đặt nó vào chương trình con và gọi nó ở cuối kịch bản của bạn:
options () {
if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist
while (( "$#" )); do # process ALL arguments
if [ "$1" = ^-t$ ]; then # -t short for "test"
# do something here THEN shift the argument
# shift removes it from $@ and reduces $# by
# one if you supply no argument
shift
# we can also process multiple arguments at once
elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments
# do something more then remove them ALL from the arg list
shift 3
else
echo "No matching arguments!"
echo "Usage: [script options list here]"
fi
done
else
echo "Usage: [script options list here]"
exit 0
fi
}
options "$@" # run options and loop through/process ALL arguments
Tôi khuyên bạn nên giới hạn tập lệnh bash của bạn dưới 400 dòng / 15k ký tự; kịch bản nói trên của tôi đã vượt quá kích thước này và trở nên rất khó để làm việc. Tôi bắt đầu viết lại nó trong Perl, phù hợp hơn cho nhiệm vụ. Hãy ghi nhớ điều đó khi bạn làm việc với các tập lệnh của mình trong bash. Bash là tuyệt vời cho các tập lệnh nhỏ và oneliners, nhưng bất cứ điều gì phức tạp hơn và tốt hơn hết bạn nên viết nó bằng Perl.
Lưu ý, tôi đã không kiểm tra những điều trên, vì vậy nó có thể không hoạt động, nhưng bạn có ý tưởng chung từ nó.
options
ở cuối là không chính xác, nó sẽ trở lại -bash: syntax error near unexpected token $@
. Gọi nó là options "$@"
.
while
kiện đó không nên (($#))
thay thế?
$#
? Chỉnh sửa: bạn đã đúng. Đã sửa nó thànhwhile (( "$#" ))
getopt
phải luôn được xác minh là GNU getopt trước khi bạn sử dụng nó, nhưng dù sao bạn cũng không nên sử dụng nó vì nó dễ mang theogetopts
hơn (và nói chung là đẹp hơn). Nếu bạn làm cần phải gọi nó là đối với một số lý do, gọi nó là một cách GNU cụ thể, và đảm bảo rằngGETOPT_COMPATIBLE
không có trong môi trường.