【问题标题】:What does the bash read -d '' do?bash read -d '' 有什么作用?
【发布时间】:2019-08-14 15:04:08
【问题描述】:

-d '' 在 bash 读取命令中做了什么?该示例直接来自a previous SO。从 read 命令打印的用法来看,-d 选项定义了用于在一行中分割单词的分隔符。空分隔符有什么作用?

read -d '' sql << EOF
select c1, c2 from foo
where c1='something'
EOF

echo "$sql"

我通过试验知道变量被分配了多行。没有它,只分配第一行。根据用法文本似乎很难解释这种行为。

【问题讨论】:

  • 空分隔符选项-d '' 用于NUL 分隔输入。
  • NUL 分隔输入是什么意思? Inserting '\0' into the string?
  • 是的 \0 是 NUL 字符
  • anubhava,也许您可​​以通过一些详细说明将此 nul 分隔符解释放入答案中。这对我来说是新事物。猜想有些人也不知道。感谢您的快速回答。
  • @minghua,……嗯? bash 字符串 绝对不能 包含 NUL 文字,句号。 '\0' 不是 NUL 文字;这只是一个转义序列,printf 会变成一个。

标签: bash delimiter readline


【解决方案1】:

read -d 将停止读取的字符从默认换行符更改为以下参数的第一个字符。

要理解的重要一点是 bash 使用 C 字符串,这些字符串由文字 NUL 终止。因此,当以下参数为'' 时,第一个(也是唯一一个)字符是终止它的 NUL;因此,当 shell 取消引用 char* 以获取它指向的第一个字符时,它会得到一个 NUL。


现在,当您使用 &lt;&lt;EOF 重定向 heredoc 时,该文档中实际上不会包含任何 NUL —— 那么您的代码是如何工作的呢?

答案是您的代码预计read 操作会失败。即使失败,read 仍会填充其目标变量;因此,如果您没有终止分隔符,read 将具有非零退出状态...但无论如何它仍然会将您想要收集的所有数据放入变量中!

对于不触发set -e错误的版本,可以考虑在读取完成后检查目标变量是否为空:

{ IFS= read -r -d '' string || [[ $string ]]; } <<'EOF'
...string goes here...
EOF

我们做了哪些改变?

  • IFS= 防止去除前导或尾随空格(或其他字符,如果 IFS 已重新定义)。
  • read -r 防止带有反斜杠文字的内容被破坏。
  • || [[ $string ]] 表示如果 read 报告失败,我们然后检查字符串是否已填充,如果变量不为空,则仍然认为整个命令成功。

【讨论】:

  • 这很有帮助。否则read -d $'\0'set -e 不兼容。当它返回非零时,read 甚至没有打印错误消息的体面:-)
【解决方案2】:

在 bash 中 read 内置空字符串分隔符 -d '' 的行为与将分隔符用作 NUL 字节或 $'\0'(由 ANSI C 引用的字符串定义)或十六进制表示 @ 987654325@.

-d '' 指定每个输入行应由 NUL 字节分隔。这意味着在每次调用read 时,都会读取输入字符串直到紧接的下一个 NUL 字符。

通常和IFS=一起使用:

IFS= read -r -d ''

用于修剪输入中的前导和尾随空格。

处理 NUL 分隔输入的常见示例是:

while IFS= read -r -d '' file; do
    echo "$file"
done < <(find . -type f -print0)
  • find 命令正在打印当前目录中的文件,其中 NUL 作为每个条目之间的分隔符。
  • read -d ''\0 设置为分隔符,用于从find 命令的输出中一次读取一个条目。

相关Why ‘read’ doesn’t accept \0 as a delimiter in this example?

【讨论】:

  • 是的,我同意$'\0' 的使用具有误导性,但bash 的行为是相同的,无论我们使用-d '' 还是-d $'0'
猜你喜欢
  • 1970-01-01
  • 2016-06-22
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 2012-05-07
  • 2016-09-10
  • 1970-01-01
  • 2014-09-07
相关资源
最近更新 更多