Bash
在 while 循環中呼叫函式時,getopts 不獲取任何參數
我試圖在傳遞一些參數的while循環中呼叫一個函式。但是,
getopts
只能獲取第一次呼叫的參數。這是一個最小的例子:
function add_all_external_services() { env | sed -n "s/^EXTERNAL_SERVICE_OPTIONS_\(.*\)$/\1/p" > options while read -r line do key="${line%%=*}" opt="${line#*=}" if [[ -n "$key" && -n "$opt" ]]; then echo "Adding external service \"$key\" with options: \"$opt\"" add_external_service $opt else echo "Missing one or more variables: - Key: \"$key\" - Options: \"$opt\" " fi done < options rm options } function add_external_service() { local local_service_name="" local external_service_name="" local external_service_namespace="" local service_url="" echo " Options: $@" while getopts l:s:n:-: OPT; do if [[ "$OPT" = "-" ]]; then # long option: reformulate OPT and OPTARG OPT="${OPTARG%%=*}" # extract long option name OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty) OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=` fi case "$OPT" in l | local-service-name) needs_arg; local_service_name="$OPTARG" ;; s | external-service-name) needs_arg; external_service_name="$OPTARG" ;; n | external-service-namespace) needs_arg; external_service_namespace="$OPTARG" ;; external-name) needs_arg; service_url="$OPTARG" ;; ??* ) die "Illegal option --$OPT" ;; # bad long option \? ) exit 2 ;; # bad short option (error reported via getopts) esac done echo " - local $local_service_name" echo " - name $external_service_name" echo " - namespace $external_service_namespace" echo " - url $service_url" }
然後,在呼叫時:
export EXTERNAL_SERVICE_OPTIONS_A="-l local_a -s rasa -n botinstance-12424526-review-feature-ce-swdjtf" export EXTERNAL_SERVICE_OPTIONS_B="-l local_b -s review-feature-ce-swdjtf -n botinstance-12424526-review-feature-ce-swdjtf" ventury-deploy add_all_external_services
我明白了:
Adding external service "B" with options: "-l local_b -s name_b -n namespace_b" Options: -l local_b -s name_b -n namespace_b - local local_b - name name_b - namespace namespace_b - url Adding external service "A" with options: "-l local_a -s name_a -n namespace_a" Options: -l local_a -s name_a -n namespace_a - local - name - namespace - url
我從這裡
getopts
得到了零件,每當我在循環外呼叫函式時它都可以正常工作。在閱讀了這個問題之後,我嘗試
&
在循環內呼叫函式後添加 a ,它可以工作……所有的參數都是由getopts
. 我不明白為什麼在後台執行命令會使其工作。如果我
echo $@
在 之前getopts
,我可以看到所有參數都正確傳遞,如果我手動呼叫第二個函式,每個 env 變數一次,它也可以正常工作。那麼,在後台執行這些命令有什麼不同呢?我的意思是,有什麼不同
getopts
?另外,為什麼echo $@
可以看到參數而getopts
不能?
這是因為您沒有重置
OPTIND
. 根據手冊:每次呼叫時,getopts 將下一個選項放入 shell 變數名中,如果 name 不存在則初始化,並將下一個要處理的參數的索引放入變數 OPTIND 中。每次呼叫 shell 或 shell 腳本時,都會將 OPTIND 初始化為 1。
因此,OPTIND 用於跟踪要處理的下一個參數,並
1
在腳本啟動時自動設置為,但在函式結束時不會重置。要修復您的腳本,只需添加
OPTIND=1
到函式的開頭:function add_external_service() { OPTIND=1 local local_service_name="" local external_service_name="" local external_service_namespace="" local service_url="" echo " Options: $@" while getopts l:s:n:-: OPT; do if [[ "$OPT" = "-" ]]; then # long option: reformulate OPT and OPTARG OPT="${OPTARG%%=*}" # extract long option name OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty) OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=` fi case "$OPT" in l | local-service-name) needs_arg; local_service_name="$OPTARG" ;; s | external-service-name) needs_arg; external_service_name="$OPTARG" ;; n | external-service-namespace) needs_arg; external_service_namespace="$OPTARG" ;; external-name) needs_arg; service_url="$OPTARG" ;; ??* ) die "Illegal option --$OPT" ;; # bad long option \? ) exit 2 ;; # bad short option (error reported via getopts) esac done echo " - local $local_service_name" echo " - name $external_service_name" echo " - namespace $external_service_namespace" echo " - url $service_url" }