文字列(変数)を分割する方法を探しています。:
他のソースから次のコマンドが見つかりました。
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_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//:/ })
交換後に分割+グローブを適用するため、間違っています。:
あなたが望むもの:
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
互換性のあるコードを書くことであり、ksh構文を使って書くことをzsh
望むかもしれません。zsh
ksh
シェルが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