使用分隔符时如何删除 readarray 添加的新行?

使用分隔符时如何删除 readarray 添加的新行?
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)。

请注意,尽管Sin 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 -fnoglob

declare -n a=$1创建一个当地的变量作为由(函数的第一个参数)a命名的全局变量的别名。$1

相关内容