短いオプションと長いオプションを分離する

短いオプションと長いオプションを分離する

短いオプション文字列と長いオプション文字列に分割したい短いオプション文字列があります。

opts="-p,--plong,--pext"

私の考えは、短いオプションに問題があるgrepを使用することです。

opts="-p,--plong,--pext"
short_opts=$(echo "$opts" | grep -o '\s*-\w*')
long_opts=$(echo "$opts" | grep -o '\s*--\w*')
echo
echo "short_opts: $short_opts"
echo "long_opts: $long_opts"

答え1

Bashの代わりにzshでは、次のことができます。

opts="-p,--plong,--pext"

# split on ,s into an array
opts=( ${(s[,])opts} )

short_opts=( ${opts:#--*} )
long_opts=( ${(M)opts:#--*} )

次に、2つの配列を取得します。

$ typeset -p short_opts long_opts
typeset -a short_opts=( -p )
typeset -a long_opts=( --plong --pext )

-短いオプションのみを許可し、その後に1つを除くすべての文字が続き、長いオプションの後に次を-除く--1つ以上の文字が続くなど、より制限的な一致を作成するには、次のようにします=

set -o extendedglob
short_opts=( ${(M)opts:#-[^-]} )
long_opts=( ${(M)opts:#--[^=]##} )

sbashには分割演算子(上記のzsh引数拡張フラグなど)はありませんが、Bourneシェルから継承された引用符なし拡張に対して悪名高い分割+globを実行します。したがって、これを使用して分割を実行できます。

IFS=, # split on ,
set -o noglob
opts=( $opts )

zsh演算子のような配列フィルタ演算子はありませんが、${array:#pattern}ksh93の配列メンバ編集演算子があり、${array[@]/pattern/replacement}引用符を持たない拡張は空の要素を削除するので、それを行うことができます(noglobまだ開いていて$IFS空であるか、まだincludeと仮定,)。

short_options=( ${opts[@]/#--*} )
long_options=( ${opts[@]/#-[!-]*} ) 

#最初にパターンを固定します。%最後にアンカーを指定しますが、zshとは異なり、bashは開始と終了でアンカーをサポートしていないため、要素全体を一致させることはできません。caseより厳しい一致が必要な場合は、いつでもすべての要素を繰り返して一致に使用できます。

short_opts=() long_opts=()
shopt -s extglob
for opt in "${opts[@]}"; do
  case $opt in
    ( -[^-]     ) short_opts+=( "$opt" );;
    ( --+([^=]) ) long_opts+=( "$opt" );;
  esac
done

kshと同様に、bashは意味を区切り記号$IFSからS区切り記号/終了記号に変更します。つまり、空の文字列a,,b,に分割され、追加の空の文字列がないことを意味します。すべての要素がオプションであれば、ここでは問題にはなりません。ab

答え2

私はすでにこれをしました

opts="-p,--plong,--pext"
for opt in ${opts//,/ }; do
  if [[ "$opt" == --* ]]; then
    long_opts="$long_opts $opt"
  elif [[ "$opt" == -* ]]; then
    short_opts="$short_opts $opt"
  fi
done

echo
echo "short_opts: $short_opts"
echo "long_opts: $long_opts"

関連情報