类似于Bourne / POSIX的shell具有split + glob运算符,每次在列表上下文中未引用参数扩展($var
,$-
...),命令替换($(...)
)或算术扩展($((...))
)时都会调用该操作符。
实际上,您在for name in ${array[@]}
而不是时错误地调用了它for name in "${array[@]}"
。(实际上,您应该注意,错误地调用该操作员是许多错误和安全漏洞的来源)。
该操作符配置有$IFS
特殊参数(以告知要分割的字符(尽管要注意空格,制表符和换行符在那里有特殊处理))和-f
禁用(set -f
)或启用(set +f
)glob
部分的选项。
还要注意,虽然S
in $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
您在使用什么,bash
IFS='_' read -a array <<< "${string}"