当设置为 var 时,如何将切片数组的输出保存为单独的项目而不是字符串?

当设置为 var 时,如何将切片数组的输出保存为单独的项目而不是字符串?

对数组进行切片时,输出将作为字符串捕获在变量中。

当直接使用切片时,它将是单独的项目。

如何将切片数组保存在变量中而不将其转换为字符串?

还有其他方法或途径可以解决这个问题吗?

例子:

# setting IFS to this, no need to quote anything
IFS=$'\n'

mapfile -t arr < <(for i in {1..6}; do echo $i; done)

declare -p arr
declare -a arr=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6")

# $() or `` give the same results  
slc=`echo ${arr[@]:0:3}`  

# proving that when the slice is saved as a var, it's a string
for i in $slc; do echo $i; done
1 2 3

# proving that when the slice is used directly the items are separate
for i in ${arr[@]:0:3}; do echo $i; done
1
2
3

请注意,它与已接受的答案一起工作;当IFS=$'\n'结果相同时,带或不带引号:

IFS=$'\n'

slc=(${arr[@]:0:3})

for i in ${slc[@]}; do echo $i; done
1
2
3

答案1

在:

echo ${arr[@]:0:3}

首先,您忘记了引号,这意味着扩展受到 split+glob 的影响(使用IFS=$'\n',仍然在换行符上拆分,并且仍在进行通配),并且使用了echo不能用于​​任意数据的内容。

echo正在传递多个参数(切片的元素进一步受到 split+glob 的影响),并且它以空格分隔打印它们。

和:

var=`echo...`

(顺便说一句,这是旧的已弃用的命令替换形式,您应该使用var=$(echo...)

shell 将该输出(减去尾随换行符)收集到标量echo变量,因为这是标量变量赋值语法,但无论如何,自从将所有内容捆绑到一个流中以来,有关每个元素开始和结束位置的信息早已丢失。

要将切片存储到变量中,您需要一个数组变量并使用数组赋值语法:

$ arr=( '*' $'\n' '' 'element '{4..6} ) # ¹
$ slc=( "${arr[@]:0:3}" )
$ typeset -p arr slc
declare -a arr=([0]="*" [1]=$'\n' [2]="" [3]="element 4" [4]="element 5" [5]="element 6")
declare -a slc=([0]="*" [1]=$'\n' [2]="")

和你做的一样:

   @slc = @arr[0..2]         # in perl
    slc = $arr( `{seq 3} )   # in rc
set slc   $arr[1..3]         # in fish
    slc=( "${arr[1,3]}" )    # in yash
    slc=( "${(@)arr[1,3]}" ) # in zsh

并循环遍历元素:

for i in "${slc[@]}"; do
  something with "$i"
done

readarray -td '' arr < <(printf '%s\0' '*' $'\n' '' 'element '{4..6}如果您必须使用readarray或其用词不当的mapfile别名,则依赖于 bash 变量或内置参数无论如何都不能包含 NUL 字符这一事实。

相关内容