Tôi đang cố gắng xây dựng một tập lệnh shell chấp nhận các tùy chọn khác nhau và getopts
có vẻ như là một giải pháp tốt vì nó có thể xử lý thứ tự biến đổi của các tùy chọn và đối số (tôi nghĩ vậy!).
Tôi sẽ chỉ sử dụng các tùy chọn ngắn và mỗi tùy chọn ngắn sẽ yêu cầu một giá trị tương ứng, ví dụ: ./command.sh -a arga -g argg -b argb
nhưng tôi muốn cho phép các tùy chọn được nhập theo thứ tự không cụ thể, như cách mà hầu hết mọi người đều quen làm việc với các lệnh shell .
Điểm khác là tôi muốn tự kiểm tra các giá trị đối số tùy chọn, lý tưởng trong các case
câu lệnh. Lý do cho điều này là việc thử nghiệm :)
trong case
tuyên bố của tôi đã mang lại kết quả không nhất quán (có thể thông qua sự thiếu hiểu biết từ phía tôi).
Ví dụ:
#!/bin/bash
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
;;
u)
MYSQL_USER=$OPTARG
;;
p)
MYSQL_PASS=$OPTARG
;;
d)
BACKUP_DIR=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
:)
echo "Option -$OPTARG requires an argument" >&2
exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
Đã thất bại cho những lần xuất hiện như thế này ... ./command.sh -d -h
Khi tôi muốn nó gắn cờ -d như yêu cầu một đối số nhưng tôi nhận được giá trị -d=-h
không phải là thứ tôi cần.
Vì vậy, tôi cho rằng việc chạy xác thực của riêng mình trong các báo cáo trường hợp sẽ dễ dàng hơn để đảm bảo rằng mỗi tùy chọn được đặt và chỉ được đặt một lần.
Tôi đang cố gắng làm như sau nhưng if [ ! "$MYSQL_HOST" ]; then
các khối của tôi không được kích hoạt.
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
if [ ! "$MYSQL_HOST" ]; then
echo "host not set"
exit 2
fi
;;
u)
MYSQL_USER=$OPTARG
if [ ! "$MYSQL_USER" ]; then
echo "username not set"
exit 2
fi
;;
p)
MYSQL_PASS=$OPTARG
if [ ! "$MYSQL_PASS" ]; then
echo "password not set"
exit 2
fi
;;
d)
BACKUP_DIR=$OPTARG
if [ ! "$BACKUP_DIR" ]; then
echo "backup dir not set"
exit 2
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
#:)
# echo "Option -$opt requires an argument" >&2
# exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
Có một lý do mà tôi không thể kiểm tra xem một cái OPTARG
có độ dài bằng không từ bên trong getopts ... while ... case
không?
Cách tốt hơn để chạy xác thực đối số của riêng tôi getopts
trong trường hợp tôi không muốn dựa vào :)
. Thực hiện xác nhận đối số của tôi bên ngoài while ... case ... esac
?
Sau đó, tôi có thể kết thúc với các giá trị đối số của -d
vv và không bắt một tùy chọn bị thiếu.
while
vòng lặp chạy qua các tùy chọn. Đây là phương pháp tôi đã thực hiện mặc dù nó dài dòng so với các phương pháp khác, nhưng rất rõ những gì đang diễn ra trong kịch bản. Và khả năng bảo trì của người khác là quan trọng trong trường hợp này.