bash/zsh에서 ':' 문자를 사용하여 문자열을 분할하는 방법은 무엇입니까?

bash/zsh에서 ':' 문자를 사용하여 문자열을 분할하는 방법은 무엇입니까?

문자열(변수)을 분할하는 방법을 찾고 있습니다.:

다른 소스에서 다음 명령을 찾았습니다.

str="part1=part2=part3"
parts=(${(@s:=:)str})
echo ${#parts[@]}

:그러나 동일한 시퀀스에 대한 이스케이프 방법을 찾을 수 없습니다.

parts=(${(@s:::)str})  #Not working
parts=(${(@s:\::)str}) #Not working

Bash의 경우 다음을 찾았습니다.

parts=(${str//:/ })

작동하지만 실제로는 호환되지 않습니다. 다음 줄을 사용하여 쉘을 구별할 수 있습니다.

if [ -z "$(ps -p $$| grep zsh)" ]; then
    echo "This is bash (Use bash solution here)"
else
    echo "This is zsh (Use Zsh solution here)"
fi

하지만 일부 대체 솔루션이 호환될 수도 있나요? 실행 가능한 솔루션은 이미 성공했습니다.

답변1

이것:

당신은 그것을 사용할 수 있습니다 :

parts=(${(s/:/)str})

다음과 같은 일부 일반적인 문자 쌍도 지원됩니다.

parts=(${(s[:])str})

이 플래그를 사용하여 @빈 요소를 유지하려면 다음을 인용해야 합니다.

parts=("${(@s[:])str}")

그렇지 않으면@

이와 같은 변수를 다루고 싶다면$PATH$LD_LIBRARY_PATHtypeset -T묶다배열 변수를 스칼라 변수로:

$ typeset -T str str_array
$ str='a::b'
$ typeset -p str
typeset -T str str_array=( a '' b )

zsh기본적으로 바인딩됩니다 $path( $PATH예: csh/tcsh

배쉬의

parts=(${str//:/ })

교체 후 분할+글로브를 적용하기 때문에 잘못된 것입니다.:

당신이 원하는 것:

IFS=:            # split on : instead of default SPC TAB NL
set -o noglob    # disable glob
parts=( $str"" ) # split+glob (leave expansion unquoted), preserve trailing
                 # empty part.

zshsh코드가 에뮬레이션 모드 인 경우 ksh코드는 에서도 실행됩니다. 당신의 목표가 bash호환되는 코드를 작성하는 것이고 ksh 구문을 사용하여 작성 zsh하고 싶을 수도 있습니다.zshksh

쉘이 bash또는 인지 테스트하려면 / 또는 변수 zsh가 있는지 테스트해야 합니다 .$BASH_VERSION$BASH_VERSINFO$ZSH_VERSION

split() { # args: string delimiter result_var
  if
    [ -n "$ZSH_VERSION" ] &&
      autoload is-at-least &&
      is-at-least 5.0.8 # for ps:$var:
  then
    eval $3'=("${(@ps:$2:)1}")'
  elif
    [ "$BASH_VERSINFO" -gt 4 ] || {
      [ "$BASH_VERSINFO" -eq 4 ] && [ "${BASH_VERSINFO[1]}" -ge 4 ]
      # 4.4+ required for "local -"
    }
  then
    local - IFS="$2"
    set -o noglob
    eval "$3"'=( $1"" )'
  else
    echo >&2 "Your shell is not supported"
    exit 1
  fi
}

split "$str" : parts

관련 정보