从Bash中的Here Document读取多行变量的完美方法是什么?
看看我的做法如何具有将1
作为$?
返回的副作用...
#!/bin/bash
printf "Unsetting...\n"
unset variable
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"
printf "\n"
printf "Setting to 'foo'...\n"
variable='foo'
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"
printf "\n"
printf "Setting to 'bar' by reading stdin from process substitution...\n"
read variable < <(echo 'bar')
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"
printf "\n"
printf "Setting to 'baz' by reading stdin from Here String...\n"
here_string='baz'
read variable <<< "${here_string}"
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"
printf "\n"
printf "Setting to 'quux' by reading stdin from Here Document...\n"
read variable <<- 'EOF'
quux
EOF
printf "Exit status: %s.\n" "$?"
printf "Variable: %s.\n" "${variable}"
printf "\n"
printf "Setting to 'thud <newline> thud' by reading stdin from Here Document...\n"
read -d '' variable <<- 'EOF'
thud
thud
EOF
printf "Exit status: %s.\n" "$?" # ONE?!one!!oneone? :)
printf "Variable: %s.\n" "${variable}"
Unsetting...
Exit status: 0.
Variable: .
Setting to 'foo'...
Exit status: 0.
Variable: foo.
Setting to 'bar' by reading stdin from process substitution...
Exit status: 0.
Variable: bar.
Setting to 'baz' by reading stdin from Here String...
Exit status: 0.
Variable: baz.
Setting to 'quux' by reading stdin from Here Document...
Exit status: 0.
Variable: quux.
Setting to 'thud <newline> thud' by reading stdin from Here
Document...
Exit status: 1.
Variable: thud
thud.
答案 0 :(得分:4)
我认为问题是read
在看到ASCII NUL字符之前看到了文件结尾。但是,如果这是真的,则以下内容应以0:
read -d '' variable <<< $'thud\nthud\x00'
但事实并非如此。
代替真正的解决方案,我可以提供以下黑客攻击。因为它阻止任何命令实际返回0,所以它不应该破坏你的登录脚本:
read -d '' variable <<-'EOF' || true
thud
thud
EOF
read
仍然退出1,但这只会导致shell执行true
命令,保证退出0。
答案 1 :(得分:3)
read
如果到达文件末尾而不按其分隔符,则返回非零值。显然\ 0被视为EOF,无论它是否是你的分隔符。防止这种情况的一个方法是选择一个不太可能的分隔符,并在最后用它填充你的字符串。例如:
read -r -d $'\3' variable <<<"thud\nthud\n"$'\3' ; echo $?
然而,那说,在heredoc中这很难做到。
答案 2 :(得分:3)
您可以将here-document读入包含mapfile
或其别名readarray
mapfile var <<-'EOF'
thud
thud
EOF
导致
var=([0]="thud
" [1]="thud
")
然后只连接数组元素,例如
variable=${var[0]}
variable+=${var[1]}
...
对于可变长度的数组,您可以循环执行此操作或使用printf
内置函数(感谢eush77):
printf -v variable "%s" "${var[@]}"
两个选项都会导致
variable=$'thud\nthud\n'
退出状态为1的原因已由Sorpigal提供..
答案 3 :(得分:3)
read
在达到EOF时返回1,同时分配最后读取的结果。这就是为什么不以换行符结尾的文件存在问题,因为带有read
的简单循环不会运行最后一行的循环体。
当您使用read -d ''
而不将NUL字节放入输入时,这就像读取文件的最后一行一样。问题是为什么你希望read
在这种情况下返回0?它正在做它应该做的事情。另请注意,heredocs(和herestrings)总是自动在末尾添加换行符。
有点相关: