类似于Bourne / POSIX的shell具有split + glob运算符,每次在列表上下文中未引用参数扩展($var,$-...),命令替换($(...))或算术扩展($((...)))时都会调用该操作符。
实际上,您在for name in ${array[@]}而不是时错误地调用了它for name in "${array[@]}"。(实际上,您应该注意,错误地调用该操作员是许多错误和安全漏洞的来源)。
该操作符配置有$IFS特殊参数(以告知要分割的字符(尽管要注意空格,制表符和换行符在那里有特殊处理))和-f禁用(set -f)或启用(set +f)glob部分的选项。
还要注意,虽然Sin $IFS最初$IFS是用于分隔符的(在Bourne shell中),S但在POSIX shell中,in字符$IFS应视为分隔符或终止符(请参见下面的示例)。
所以分裂_:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
array=($string) # invoke the split+glob operator
for i in "${array[@]}"; do # loop over the array elements.
要查看分隔符和分隔符之间的区别,请尝试:
string='var1_var2_'
这会将其拆分为var1和var2(没有多余的空元素)。
因此,要使其类似于JavaScript的split(),您需要一个额外的步骤:
string='var1_var2_var3'
IFS=_ # delimit on _
set -f # disable the glob part
temp=${string}_ # add an extra delimiter
array=($temp) # invoke the split+glob operator
(请注意,它将像JavaScript一样将一个空元素拆分$string为1(不是0)元素split())。
要查看特殊处理标签,空格和换行符,请比较:
IFS=' '; string=' var1 var2 '
(您到达的位置var1和var2)与
IFS='_'; string='_var1__var2__'
你在哪里得到:'',var1,'',var2,''。
请注意,zsh除非在in sh或ksh仿真中,shell不会像那样隐式调用该split + glob运算符。在那里,您必须显式调用它。$=string对于split部分,$~string对于glob部分($=~string对于两者),它还具有split运算符,您可以在其中指定分隔符:
array=(${(s:_:)string})
或保留空元素:
array=("${(@s:_:)string}")
请注意,这里s是用于split而不是定界的(也与$IFS已知的POSIX不符合zsh)。与JavaScript的不同之处split()在于,将空字符串拆分为0(而不是1)元素。
有一个显着区别$IFS-splitting的是,${(s:abc:)string}在分割abc字符串,同时用IFS=abc,将拆分上a,b或c。
使用zsh和时ksh93,可以通过在中加倍删除空格,制表符或换行符的特殊处理$IFS。
作为历史记录,Bourne外壳(祖先外壳或现代POSIX外壳)始终会剥离空元素。它还有许多与$ @的拆分和扩展有关的错误,非默认值为$IFS。例如,IFS=_; set -f; set -- $@将不等同于IFS=_; set -f; set -- $1 $2 $3...。
拆分正则表达式
现在,对于更接近JavaScript且split()可以在正则表达式上拆分的内容,您需要依赖外部实用程序。
在POSIX工具箱中,awk有一个split运算符,可以对扩展的正则表达式进行拆分(这些正则表达式或多或少是JavaScript支持的类似Perl的正则表达式的子集)。
split() {
awk -v q="'" '
function quote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split(ARGV[1], a, ARGV[2])
for (i = 1; i <= n; i++) printf " %s", quote(a[i])
exit
}' "$@"
}
string=a__b_+c
eval "array=($(split "$string" '[_+]+'))"
该zsh外壳具有内建的Perl兼容的正则表达式(其支持zsh/pcre模块),但用它来分割字符串,但可能是比较麻烦的。
shell您在使用什么,bashIFS='_' read -a array <<< "${string}"