짧은 옵션과 긴 옵션을 분리하세요

짧은 옵션과 긴 옵션을 분리하세요

짧은 옵션 문자열과 긴 옵션 문자열로 분할하려는 짧은 옵션 문자열이 있습니다.

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:#--*} )

그런 다음 두 개의 배열을 얻습니다.

$ 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:#--[^=]##} )

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"

관련 정보