Bash

如何在 bash/zsh 中用 ‘:’ 字元分割字元串?

  • October 13, 2020

我正在尋找:一種在 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

但也許一些替代解決方案是兼容的?任何可行的解決方案已經是一個勝利。

:任意字元:

您可以使用:

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

還支持一些常見的字元對,例如:

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

如果您要使用@標誌來保留空元素,那麼您需要引用:

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

否則@沒有區別。

如果要處理$PATH/ $LD_LIBRARY_PATH… 之類的變數,另請參閱typeset -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//:/ })

:錯誤,因為它在替換為 SPC後應用了 split+glob 。

你會想要:

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.

zsh如果它處於仿真模式sh,該程式碼也可以在. ksh如果您的目標是編寫與bash和兼容的程式碼zsh,您可能希望使用 ksh 語法編寫它,並確保在解釋它時將其zsh置於ksh仿真中(可能僅在某些函式本地)。

要測試 shell 是否是bashor zsh,您需要測試$BASH_VERSION/ $BASH_VERSINFOor$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

引用自:https://unix.stackexchange.com/questions/614299