-bash:警告:命令替换:忽略输入中的空字节

时间:2020-10-27 08:14:15

标签: bash variables calculation

我总是得到

-bash: warning: command substitution: ignored null byte in input

执行以下代码时发出警告:

BW=`bc <<< "$(cat $TMP | grep -Pzo '(?<="outgoing_traffic": )(.*)(?=,)')/1024^3"`

如果结果不为零,也会出现该警告。

如何避免这种情况?

当错误真正为0时,如何跳过该错误?

更新,我尝试了以下提供的解决方案:

tr -d '\0' 

但是该代码不起作用:

BW=tr -d '\0'  < `bc <<< "$(cat $TMP | grep -Pzo '(?<="outgoing_traffic": )(.*)(?=,)')/1024^3"`

输出:

-bash: warning: command substitution: ignored null byte in input
-bash: `bc <<< "$(cat $TMP | grep -Pzo '(?<="outgoing_traffic": )(.*)(?=,)')/1024^3"`: No such file or directory

有趣的事实,它不是0

BW=`bc <<< "$(cat $TMP | grep -Pzo '(?<="outgoing_traffic": )(.*)(?=,)')/1024^3"`
echo $BW

输出:

-bash: warning: command substitution: ignored null byte in input
4

1 个答案:

答案 0 :(得分:1)

您会收到警告,因为grep -z在结果的末尾输出了一个零字节,而Shell无法对此进行处理。最简单的解决方案是删除该选项,或找到一种用Shell实际可以处理的东西替换该选项的方法。实际上,它似乎在这里没有任何用处……但可能会丢失useless cat并使用现代命令替换语法而不是过时的反引号和fix the quoting.

BW=$(bc <<< "$(grep -Po '(?<="outgoing_traffic": )(.*)(?=,)' <"$TMP")/1024^3")

顺便说一句,tr命令不起作用的原因之一是您放了反引号。另外,<之后的符号必须是文件名。正确的语法看起来像

BW=$(bc <<< "$(grep -Pzo '(?<="outgoing_traffic": )(.*)(?=,)' <"$TMP" | tr -d '\0')/1024^3")

但是如上所述,如果您不希望零字节,请不要使用-z选项。

零字节有时有用的原因是,如果要打印文件名,那是文件名中唯一不允许使用的字符,因此在处理文件时用作分隔符是很有用的。 (初学者经常对Unix文件名可以包含引号和换行符感兴趣;但是它们可以。这可能是导致Shell脚本中错误的第一大原因-初学者往往只对琐碎的文件名进行测试,并产生与真实文件名相冲突的代码。 -world文件。)

只需说明一下,零字节不是数字0;它是一个ASCII码为零的字符。 (因此,是ctrl-A之前的字符,它是ASCII代码1,等等。有时您会看到它被称为ctrl- @。)您可以在十六进制转储中看到它,例如:

bash$ echo hello | tr '\n' '\0' | xxd
00000000: 6865 6c6c 6f00                           hello.

以上命令将换行符替换为零字节(ASCII码十六进制00)。您可以省略tr来查看换行符的ASCII码(十六进制0A,又名ctrl-J)。

相切地,两者之间的区别

bc <<<"one"

bc <"two"

是后者说要从文件two读取输入,而第一个只是将字符串one作为标准输入传递给bc。还有<<separator,它可以在一行中单独提供直到下一次出现separator的文字文本,作为命令的标准输入(称为“此处文档”)。

所以这个

echo 2/3 | bc

等同于

echo 2/3 > file
bc <file
rm file

cat <<here >file
2/3
here
bc <file
rm file

bc <<<2/3

除外,在第一个示例或最后一个示例中没有物理文件,并且最后一个示例仅是Bash,而其他示例与任何Bourne家族外壳兼容。如果您需要编写更多的Shell脚本,请阅读有关重定向的介绍。