读取以空字符分隔的字段

4

鉴于这个文件

printf 'alpha\0bravo\0charlie' > delta.txt

我希望将字段读入单独的变量中。我使用空分隔符的原因是因为这些字段将包含文件路径,而文件路径可以包含除了null之外的任何字符。我尝试了以下命令:

IFS= read mike november oscar < delta.txt
IFS=$'\0' read mike november oscar < delta.txt

然而,这些字段并没有被正确地分割。
$ echo $mike
alphabravocharlie

我不相信文件路径中除了空字符以外还包含其他字符。 - Marichyasana
2个回答

3

赋值语句 IFS=$'\0' 并不会将空字符作为分隔符,因为在 Bash 中,变量无法保存空字符,详情请参考这里。实际上,IFS=$'\0' 等同于 IFS=,可以通过以下方式验证:

bash-4.3$ IFS=$'\0'
bash-4.3$ echo ${#IFS}
0
IFS=的定义是完全不进行单词拆分(详见Bash参考手册)。
你可以使用read内建命令-d选项逐个读取空字节分隔的项目。根据链接的文档,我们可以使用一个空字符串作为delim来得到所需的行为。
以下是示例(我稍微添加了一些空格以演示它如何实现你想要的-不会在空格上进行拆分):
bash-4.3$ printf 'alpha with whitespace\0bravo with whitespace\0charlie with whitespace' > delta.txt
bash-4.3$ { read -r -d '' mike; IFS= read -r -d '' november; IFS= read -r -d '' oscar; echo $mike; echo $november; echo $oscar; } < delta.txt
alpha with whitespace
bravo with whitespace
charlie with whitespace

我还使用了-r选项来保留输入文件中的反斜杠。当然,您可以在开头将< delta.txt替换为cat delta.txt |
我知道逐个阅读很烦人,但我想不出更好的办法。

这个问题(以及许多其他问题)在http://mywiki.wooledge.org/BashFAQ/001上有详细介绍。 - Etan Reisner

1
作为解决方法,我创建了这个函数。
function read_loop {
  while [ "$#" -gt 0 ]
  do
    read -d '' "$1"
    shift
  done
}

示例用法
read-nul mike november oscar < delta.txt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接