Bash
如何在 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
但也許一些替代解決方案是兼容的?任何可行的解決方案已經是一個勝利。
有
:
任意字元:您可以使用:
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 是否是
bash
orzsh
,您需要測試$BASH_VERSION
/$BASH_VERSINFO
or$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