我有这个脚本,它似乎printf '%s\0%s\0'
以代码 1 退出,我不明白为什么。
我甚至强迫它使用 bash 版本 5.2 - 结果相同。
以下是示例脚本及其输出
#!/usr/bin/env bash
echo $BASH_VERSION
set -x
set -Eeuo pipefail
function prompt_creds {
local username password
read -rp "username " username
read -rsp "password " password
printf '%s\0%s\0' "${username}" "${password}"
}
function main() {
IFS=$'\0' read -r username password < <(prompt_creds )
echo "name name is ${username}" "my password is ${password}"
}
main
使用和输出
./sample.sh
3.2.57(1)-release
+ set -Eeuo pipefail
+ main
+ IFS=
+ read -r username password
++ prompt_creds
++ local username password
++ read -rp 'username ' username
username user
++ read -rsp 'password ' password
password ++ printf '%s\0%s\0' user pass
bash-5.2$ echo $?
1
我甚至尝试在 CLI 上简单运行它,并且它可以工作:
bash-5.2$ IFS=$'\0' read -r u p < <(printf '%s\0%s\0' user pass)
bash-5.2$ echo $u $p
userpass
bash 不支持变量中的 NUL 字符(据我所知只有 zsh 支持)。
IFS=$'\0'
实际上设置IFS
为空,并且该设置read -r u p
给出包含 user-NUL-pass-NUL 的输入:分配
userpass
给 u(丢弃 NUL)为 p分配空值
设置退出状态为 1,因为
read
without-d
需要一行(以换行符结尾),而 withset -e
实际上这会导致你main
立即退出您的上一个测试实际上没有起作用;如果 u=user 和 p=pass 如您所愿,它会显示
user pass
notuserpass
。并且您的交互式 shell 没有,set -e
因此它忽略了退出状态。尝试一下
{ read -rd '' u; read -rd '' p; } < <(prompt_creds)
或者使用换行符(不能出现在您的任何一个值中)作为分隔符:
但是这仍然会设置状态 1,如果 则中止
set -e
;要修复该问题,要么添加\0
到末尾,要么使用标准 set-e-nots: 。或者当然一开始mayfail || true
mayfail || :
! mayfail
if mayfail; then :; fi
就不要使用。set -e
printf
在这种情况下您可以避免使用: