将空头期权与多头期权分开

将空头期权与多头期权分开

我有一串短选项和选项,我想将其分成短选项字符串和长选项字符串。

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

在 zsh 而不是 bash 中,你可以这样做:

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

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

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

然后,你得到两个数组:

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

要进行更严格的匹配,例如仅允许短选项后跟-一个除 之外的任意一个字符-,以及长选项--后跟一个或多个除 之外的字符=

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

bash 没有拆分运算符(如s上面 zsh 的参数扩展标志),但它在从 Bourne shell 继承的未加引号的扩展上执行臭名昭著的 split+glob。所以你可以用它来进行分割:

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

它没有像 zsh${array:#pattern}操作符那样的数组过滤操作符,但它有 ksh93 的${array[@]/pattern/replacement}数组成员编辑操作符,并且不加引号的扩展会删除空元素,所以你可以这样做(假设noglob仍然打开并且$IFS为空或仍然只包含,):

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 将含义$IFSS分隔符更改为分隔符/终止符,这意味着a,,b,将被拆分为a,空字符串并且b没有额外的空字符串。如果所有元素都是选项,这里就不是问题

答案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"

相关内容