我想从NUL分离的输入(来自stdin)创建一个bash数组。
以下是一个例子:
## Let define this for clarity
$ hd() { hexdump -v -e '/1 "%02X "'; echo ;}
$ echo -en "A B\0C\nD\0E\0" | hd
41 20 42 00 43 0A 44 00 45 00
所以这是我的意见。
现在,如果不使用-a
read
命令,使用NUL可以正常工作:
$ while read -r -d '' v; do echo -n "$v" | hd; done < <(echo -en "A B\0C\nD\0E\0")
41 20 42
43 0A 44
45
我们得到正确的值。但我无法使用-a
存储这些值:
$ read -r -d '' -a arr < <(echo -en "A B\0C\nD\0E\0")
$ declare -p arr
declare -a arr='([0]="A" [1]="B")'
这显然不是我想要的。我想:
$ declare -p arr
declare -a arr='([0]="A B" [1]="C
D" [2]="E")'
有没有方法可以使用read -a
,如果它不起作用,为什么?您是否知道一种简单的方法(避免while
循环)?
答案 0 :(得分:6)
read -a
是错误的工具。它只支持非NUL分隔符。适当的技术在BashFAQ #1中给出:
arr=()
while IFS= read -r -d '' entry; do
arr+=( "$entry" )
done
对于为什么 read -d '' -a
是错误的工具:-d
给read
一个参数来确定何时完全停止阅读,而不是停止阅读单个元素。
考虑:
while IFS=$'\t' read -d $'\n' words; do
...
done
...这将读取由制表符分隔的单词,直到它到达换行符。因此,即使使用read -a
,使用-d ''
也会读取,直到达到NUL 。
你想要什么,阅读直到没有更多的内容可用并被NUL分割,不是NUL的'-d',而是根本没有行尾字符(和空IFS
) 。这不是read
目前使用的内容。
答案 1 :(得分:1)
bash-4.4-alpha为-d
添加了mapfile
选项:
`mapfile&#39; builtin现在有一个-d选项来使用任意的 字符 作为记录分隔符,以及用于将分隔符剥离为的-t选项 随-d。提供。
使用这个,我们可以简单地写:
mapfile -t -d '' arr < <(echo -en "A B\0C\nD\0E\0")
答案 2 :(得分:0)
如果有人想知道,这里的功能(使用while
)用于存储来自NUL
的值stdin
:
read_array () {
local i
var="$1"
i=0
while read -r -d '' value; do
printf -v "$var[$i]" "%s" "$value"
i=$[$i + 1]
done
}
然后可以非常干净地使用它:
$ read_array arr < <(echo -en "A B\0C\nD\0E\0")
$ declare -p arr
declare -a arr='([0]="A B" [1]="C
D" [2]="E")'
答案 3 :(得分:0)
这是@ vaab功能的简化。它使用bash 4.3's nameref功能:
read_array () {
local -n a=$1
while read -r -d '' value; do
a+=("$value")
done
}
测试:
test_it () {
local -a arr
read_array arr < <(echo -en "A B\0C\nD\0E\0")
declare -p arr
}
test_it