2014-01-11 52 views
1

我正在嘗試編寫一個Bash腳本,該腳本可以接受非POSIX方式的命令行參數。具體來說,我想用標準方式解析命令行參數,使用getopts,而也是建立命令行參數列表意外getopts及其選項字符串。下面的代碼註釋中顯示了以我描述的方式解析示例命令行參數。我接近的解決方案,但我的腳本只能識別獨特的意外的參數,而我需要識別所有意外的參數。我希望能夠解決這個問題的指導(可能通過聰明的AWK腳本)。非常感謝您的幫助。使用AWK和getopts解析非POSIX命令行參數

#!/bin/bash 
################################################################################ 
# 
# This is a test of command line parameter parsing that is explicitly non-POSIX. 
# This approach handles 
#  - options (for getopts) 
#  - arguments of options (for getopts) 
#  - positional arguments (for getopts) and 
#  - non-option arguments (command line parameters not expected by getopts). 
# All non-option arguments are placed in the string non_option_parameters. The 
# silent error reporting mode of getopts is required. Following command line 
# parameter parsing, input information can be accepted based on internal 
# priority assumptions. 
# 
# example usage: 
#  ./script.sh 
#   non-option parameters: 
#  ./script.sh -a Dirac 
#   -a triggered with parameter Dirac 
#   non-option parameters: 
#  ./script.sh -a Dirac -b 
#   -a triggered with parameter Dirac 
#   -b triggered 
#   non-option parameters: 
#  ./script.sh -a Dirac Feynman -b 
#   -a triggered with parameter Dirac 
#   -b triggered 
#   non-option parameters: Feynman 
#  ./script.sh -a Dirac Feynman Born -b 
#   -a triggered with parameter Dirac 
#   -b triggered 
#   non-option parameters: Feynman Born 
#  ./script.sh -a Dirac Feynman Born Born -b 
#   -a triggered with parameter Dirac 
#   -b triggered 
#   non-option parameters: Feynman Born 
# 
# WANT: 
#  ./script.sh -a Dirac Feynman Born Born -b 
#   -a triggered with parameter Dirac 
#   -b triggered 
#   non-option parameters: Feynman Born Born 
# 
################################################################################ 

option_string=":a:b" 
non_option_parameters="" 

process_arguments(){ 
    OPTIND=1 
    while getopts "${option_string}" option; do 
     case ${option} in 
      a) 
       echo "-a triggered with parameter "${OPTARG}"" >&2 # output to STDERR 
       ;; 
      b) 
       echo "-b triggered" >&2 # output to STDERR 
       ;; 
      \?) 
       echo "invalid option: -"${OPTARG}"" >&2 # output to STDERR 
      ;; 
     esac 
    done 
    shift $(expr ${OPTIND} - 1) 
    echo "[email protected]" 
} 

parameters="${@}" 
while [ ! -z "${parameters}" ]; do 
    parameters="$(process_arguments ${parameters})" 
    TEMP=$(echo "${parameters}" | awk -F " " '{print $1}') 
    IS_POS="$(echo "${option_string}" | sed 's/^:-://' | sed 's/\([a-zA-Z]\)/\ \1/g' | sed 's/\([a-zA-Z]\)/-\1/g' | sed 's/://g' | awk -v OPTION=${TEMP} \ 
    '{ 
     for(i=1; i<=NF; i++){ 
      if((match($i, OPTION)== 1) && (length($i) == length(OPTION))){ 
      print $i 
     } 
     } 
    }' \ 
    | wc -l)" 
    # The AWK code is quivalent to grep -w "-OPTIONCHAR". Note the trailing '-' 
    # character behind OPTIONCHAR). IS_POS tells whether the first element in a 
    # space-delimited string of parameters is a positional argument. 
    [ ${IS_POS} -eq 0 ] && non_option_parameters="${non_option_parameters} ${TEMP}" 
    T_ARRAY="" 
    for parameter in ${parameters}; do 
     [ $IS_POS -eq 0 ] && [ "${TEMP}" == "${parameter}" ] && continue 
     T_ARRAY="${T_ARRAY} ${parameter}" 
    done 
    parameters="${T_ARRAY}" 
done 
echo "non-option parameters:${non_option_parameters}" 

回答

1

你可以儘量簡化你的腳本如下:

non_option_par="" 
par="${@}" 
while [ ! -z "${par}" ]; do 
    par="$(process_arguments ${par})" 
    non_option_par="${non_option_par} "$(awk -F'[ \t]*-' '{print $1}' <<<"$par") 
    par=$(awk -F'[ \t]*-' 'NF>1{print substr($0,index($0,"-"))}' <<<"$par") 
done 
echo "non-option parameters:${non_option_par}" 

(只要保持process_arguments功能,因爲它是..)

+0

非常感謝您的幫助。你的AWK編碼比我的更好! – d3pd

2

我不太明白IS_POS變量應該做什麼。我的機器上一直是0(mac)。第二個「Born」的問題在於T_ARRAY的構建。當我將其更改爲以下:

T_ARRAY=$(echo "${parameters}" | awk -F " " 'NF > 1 { for(i=2; i<=NF; i++) printf("%s%s", $i, i == NF ? "" : " "); next }') 

然後我得到所需的輸出:

% script.sh -a Dirac Feynman Born Born -b 
-a triggered with parameter Dirac 
-b triggered 
non-option parameters: Feynman Born Born 

我認爲這個問題是與

[ $IS_POS -eq 0 ] && [ "${TEMP}" == "${parameter}" ] && continue 

for parameter循環匹配太多次。更換awk只是刪除參數中的第一個元素 - 顯然它不會注意到IS_POS。如果在你的系統上IS_POS非零,那麼你可能需要改變它。

+0

非常感謝你對你的幫助。該匹配次數過多的循環很好被發現。 – d3pd