输出包含空格的元素的数组

时间:2011-07-23 22:00:45

标签: arrays bash

我已经成功地创建了一个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")" ),但我不知道如何嵌套引号。

2 个答案:

答案 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

不知道是否有更清洁的方式,避免全局变量,但我怀疑。