我正在寻找一种方法来分割字符串(变量):
从不同的来源,我发现了以下命令:
str="part1=part2=part3"
parts=(${(@s:=:)str})
echo ${#parts[@]}
但是,我找不到:
相同序列的逃脱方法
parts=(${(@s:::)str}) #Not working
parts=(${(@s:\::)str}) #Not working
对于 bash,我发现了这个:
parts=(${str//:/ })
哪个有效,但并不真正兼容。我可以使用以下行来区分 shell:
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_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//:/ })
是错误的,因为它在替换后应用 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
或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