$myscript.sh -host blah -user blah -pass blah
Tôi muốn chuyển đối số vào đó.Phân tích cú pháp đối số tập lệnh shell
Tôi đang sử dụng để làm $1
, $2
, $3
.... nhưng tôi muốn bắt đầu đặt tên cho chúng
$myscript.sh -host blah -user blah -pass blah
Tôi muốn chuyển đối số vào đó.Phân tích cú pháp đối số tập lệnh shell
Tôi đang sử dụng để làm $1
, $2
, $3
.... nhưng tôi muốn bắt đầu đặt tên cho chúng
Có rất nhiều cách để phân tích lập luận trong sh. Getopt là tốt. Dưới đây là một kịch bản đơn giản mà phân tích mọi thứ bằng tay:
#!/bin/sh
while echo $1 | grep -q ^-; do
eval $(echo $1 | sed 's/^-//')=$2
shift
shift
done
echo host = $host
echo user = $user
echo pass = $pass
echo args = [email protected]
Một chạy mẫu trông giống như:
$ ./a.sh -host foo -user me -pass secret some args
host = foo
user = me
pass = secret
args = some args
Lưu ý rằng đây không phải là thậm chí từ xa mạnh mẽ và ồ ạt mở đối với an ninh lỗ kể từ khi một kịch bản eval của chuỗi được xây dựng bởi người dùng. Nó chỉ là có nghĩa là để phục vụ như là một ví dụ cho một cách có thể để làm việc. Một phương pháp đơn giản hơn là yêu cầu người dùng chuyển dữ liệu trong môi trường. Trong một vỏ bourne (ví dụ, bất cứ điều gì đó không phải là trong gia đình csh):
$ host=blah user=blah pass=blah myscript.sh
hoạt động độc đáo, và các biến $host
, $user
, $pass
sẽ có sẵn trong kịch bản.
#!/bin/sh
echo host = ${host:?host empty or unset}
echo user = ${user?user not set}
...
Sử dụng 'declare' thay vì' eval' sẽ an toàn hơn. –
Ngoài đề xuất của @ DennisWilliamson, tôi khuyên bạn nên xóa '| tr -d '\ 012'', vì nó không cần thiết - việc thay thế lệnh tự động trims tất cả các dòng mới. – mklement0
@ mklement0 Tôi tin rằng tôi đã thực sự có ý thức suy nghĩ về dòng mới nội bộ, đó là lẻ xem xét rằng cố gắng để đối phó với đó là một nỗ lực để thêm mạnh mẽ cho một ý tưởng đó là vô lý mong manh. Có rất nhiều cách rất dễ vỡ, nó quá buồn cười. –
@Zac tốt, cảm ơn. –
Lưu ý rằng 'getopts' là một nội trang Bash trong khi' getopt' là một tiện ích bên ngoài. Công cụ trước chỉ hoạt động với các tùy chọn ngắn (ví dụ: '-e') trong khi tùy chọn sau cũng sẽ hoạt động với các tùy chọn dài (ví dụ:' -foo'). Lưu ý rằng có một số [vấn đề] (http://mywiki.wooledge.org/BashFAQ/035) mà sau này phải được giải quyết (các phiên bản sau của 'getopt' có ít vấn đề hơn). –
Đây là một cách đơn giản để xử lý tùy chọn cả dài và ngắn:
while [[ $1 == -* ]]; do
case "$1" in
-h|--help|-\?) show_help; exit 0;;
-v|--verbose) verbose=1; shift;;
-f) if (($# > 1)); then
output_file=$2; shift 2
else
echo "-f requires an argument" 1>&2
exit 1
fi ;;
--) shift; break;;
-*) echo "invalid option: $1" 1>&2; show_help; exit 1;;
esac
done
Từ How can I handle command-line arguments (options) to my script easily?
+1; tuy nhiên, lưu ý rằng điều này sẽ không xử lý các tùy chọn _compressed_, chẳng hạn như '-vf' để biểu diễn' -v -f'. – mklement0
giả đã sử dụng trên William Pursell dụ (với lời khuyên Dennis Williamson) cho các thông số ở định dạng này : tập lệnh -param1 = value1 -param2 = value2 ...
Đây là mã với trình phân tích cú pháp đối số một dòng (lưu nó trong tệp 'tập lệnh') :
#!/bin/bash
while echo $1 | grep ^- > /dev/null; do declare $(echo $1 | sed 's/-//g' | sed 's/=.*//g' | tr -d '\012')=$(echo $1 | sed 's/.*=//g' | tr -d '\012'); shift; done
echo host = $host
echo user = $user
echo pass = $pass
Bạn gọi nó là như thế:
script -host=aaa -user=bbb -pass=ccc
và kết quả là
host = aaa
user = bbb
pass = ccc
Đừng ai biết mã ngắn hơn để phân tích lý lẽ hơn thế này ở trên không?
Xem xét các tùy chọn không phân luồng nhưng chuyển các giá trị thông qua môi trường: ví dụ: "host = hostname user = me myscript.sh" –
trùng lặp của http://stackoverflow.com/questions/192249/how-do-i-parse-command -line-arguments-in-bash, có một câu trả lời rất hay so sánh 'bash',' getopts' (built-in shell) và 'getopt' (không được khuyến nghị trừ khi nó là phiên bản util-linux và bạn sử dụng nó) các tính năng không phải POSIX để tránh các vấn đề với arg trống, v.v.) –