我已经成功地创建了一个join函数,它使用分隔符将数组连接到一个字符串:
function join() # Usage: string=$(join "delimeter" "${array[@]}" )
{
local array=( "${@:2}" )
OLD_IFS="$IFS"
IFS="$1"
local string="${array[*]}"
IFS="$OLD_IFS"
echo "$string"
}
我也尝试过制作一个与之相反的分割函数:
function split() # Usage: array=( $(split "delimeter" "$string") )
{
OLD_IFS="$IFS"
IFS="$1"
local array=( $2 )
IFS="$OLD_IFS"
echo "${array[@]}"
}
但是,当我使用split命令并且结果包含空格时,它将无法按预期工作。 例如:
array=( "foo" "bar" "baz" "foo bar" )
string=$(join "|" "${array[@]}")
echo $string
array=( $(split "|" "$string") )
for i in ${array[@]}
do
echo $i
done
最后一个元素“foo bar”也被拆分了。
我认为解决方案是你必须做array=( "$(split '|' "$string")" )
,但我不知道如何嵌套引号。
答案 0 :(得分:3)
请注意,IFS可以是函数中的局部变量,因此您不必备份和恢复其值:
join () { local IFS="$1"; local s="${@:2}"; printf "%s" "$s"; }
这是一个需要eval的分割实现:
# usage: split varName separator stringToSplit
split () {
local var="$1"
local IFS="$2"
set -- $3
echo "declare -a $var=( $(printf "\"%s\" " "$@") )"
}
示范
$ a=( foo bar "hello world" baz )
$ s=$(join , "${a[@]}")
$ echo $s
foo,bar,hello world,baz
$ split b , "$s"
declare -a b=( "foo" "bar" "hello world" "baz" )
$ eval $(split b , "$s")
$ for x in "${b[@]}"; do echo "$x"; done
foo
bar
hello world
baz
答案 1 :(得分:2)
问题发生在split ()
功能的最后。您将数组序列化回字符串!所以它再次被空格分隔,不能识别空间是否在项目内。所以,我知道它不是很干净,但你必须使用全局变量从split()
函数返回值(在示例中省略关键字local
,并简化调用,并且对于for命令和其他一些外观变化的双引号,它起作用......:
function split() # Usage: array=( $(split "delimeter" "$string") )
{
OLD_IFS="$IFS"
IFS="$1"
array2=( $2 )
IFS="$OLD_IFS"
}
array=( "foo" "bar" "baz" "foo bar" )
string=$(join "|" "${array[@]}")
echo $string
split "|" "$string"
for i in "${array2[@]}"
do
echo $i
done
不知道是否有更清洁的方式,避免全局变量,但我怀疑。