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

use*_*544 15 bash bash-array

VAR=a,b,c,d
# VAR=$(echo $VAR|tr -d '\n')
echo "[$VAR]"
readarray -td, ARR<<< "$VAR"
declare -p ARR
Run Code Online (Sandbox Code Playgroud)

结果:

[a,b,c,d]
declare -a ARR=([0]="a" [1]="b" [2]="c" [3]=$'d\n')
Run Code Online (Sandbox Code Playgroud)

我怎么能告诉readarray不要添加最后的换行符\n?最新的$符号是什么意思?

Ini*_*ian 23

隐式尾随换行符不是readarray内置字符添加的,而是由 的 here-string ( <<<) 添加的bash,请参阅为什么 bash here-string 添加尾随换行符?. 您可以通过打印没有换行符的字符串来摆脱printf它,并通过过程替换技术读取它< <()

readarray -td, ARR < <(printf '%s' "$VAR")
declare -p ARR
Run Code Online (Sandbox Code Playgroud)

现在会正确生成

declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
Run Code Online (Sandbox Code Playgroud)

  • 哇!我永远不会发现这个。谢谢 (3认同)

Sté*_*las 5

您可以使用 split+glob (当您在列表上下文中不引用扩展时会发生什么)。大多数时候它会妨碍我们,当我们真正需要它时不使用它会很遗憾:

IFS=,
set -o noglob

ARR=($VAR) # split+glob with glob disabled, and split using , as delimiter
Run Code Online (Sandbox Code Playgroud)

这比编写一个临时文件然后readarray像在readarray <<< "$string"方法中那样调用它稍微不那么复杂(另请注意,readarray -d需要一个最新版本的bash)。

请注意,尽管使用了Sin IFS(代表separator),它的工作方式与拆分为,并且仅readarray在 中的工作方式相同。a,,b,"a""""b"

对于真正的拆分运算符,您可以zsh改用:

ARR=("${(@s:,:)VAR}")
Run Code Online (Sandbox Code Playgroud)

@和双引号保留空元素)。