VAR=a,b,c,d
# VAR=$(echo $VAR|tr -d '\n')
echo "[$VAR]"
readarray -td, ARR<<< "$VAR"
declare -p ARR
结果:
[a,b,c,d]
declare -a ARR=([0]="a" [1]="b" [2]="c" [3]=$'d\n')
我怎么知道readarray
不添加最后的换行符\n
?最新的符号是什么意思$
?
答案1
隐式尾随换行符是不是由readarray
内置添加,但由 的here-string ( <<<
)添加bash
,请参阅为什么 bash here-string 添加尾随换行符?。您可以通过打印不带换行符的字符串printf
并使用进程替换技术读取它来摆脱这种情况< <()
readarray -td, ARR < <(printf '%s' "$VAR")
declare -p ARR
现在会正确生成
declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
答案2
您可以使用 split+glob (当您在列表上下文中保留不带引号的扩展时会发生什么)。大多数时候它会妨碍我们,当我们真正需要它时不使用它将是一种耻辱:
IFS=,
set -o noglob
ARR=($VAR) # split+glob with glob disabled, and split using , as delimiter
这比编写临时文件然后readarray
像方法中那样调用它要简单一些readarray <<< "$string"
(另请注意,readarray -d
需要最新版本的bash
)。
请注意,尽管S
in IFS
(代表分隔器),其工作方式与拆分readarray
为,且仅的方式相同。a,,b,
"a"
""
"b"
对于真正的分割运算符,您可以使用zsh
:
ARR=("${(@s:,:)VAR}")
(the@
和双引号保留空元素)。
答案3
@StéphaneChazelas 答案的罐装版本:
# usage: setarray varname sep string
setarray(){ declare -n a=$1; local IFS=$2 -; set -f; a=($3); }
$ setarray arr , 1,2,3,
$ declare -p arr
declare -a arr=([0]="1" [1]="2" [2]="3")
$ setarray path : "$PATH"
$ setarray ld_preload ': ' "$LD_PRELOAD" # its elements can be separated by either ':' or spaces
...
将使( )local -
之类的选项成为函数的局部选项,就像变量一样。set -f
noglob
将declare -n a=$1
创建一个当地的变量作为由(函数的第一个参数)a
命名的全局变量的别名。$1