从NUL分离的输入中填充bash数组

时间:2014-05-05 13:49:55

标签: arrays bash stdin nul

我想从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循环)?

4 个答案:

答案 0 :(得分:6)

正如你所注意到的,

read -a是错误的工具。它只支持非NUL分隔符。适当的技术在BashFAQ #1中给出:

arr=()
while IFS= read -r -d '' entry; do
  arr+=( "$entry" )
done

对于为什么 read -d '' -a是错误的工具:-dread一个参数来确定何时完全停止阅读,而不是停止阅读单个元素。

考虑:

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。提供。

     

- https://tiswww.case.edu/php/chet/bash/CHANGES

使用这个,我们可以简单地写:

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