两个重要的陷阱
到目前为止,其他答案都忽略了这些答案:
- 从命令扩展中删除尾随换行符
- NUL字符删除
从命令扩展中删除尾随换行符
这是一个问题:
value="$(cat config.txt)"
类型解决方案,但不适用于read
基础解决方案。
命令扩展删除尾随的换行符:
S="$(printf "a\n")"
printf "$S" | od -tx1
输出:
0000000 61
0000001
这打破了从文件读取的幼稚方法:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIX解决方法:在命令扩展中附加一个额外的字符,并在以后将其删除:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
输出:
0000000 61 0a 0a
0000003
几乎是POSIX的解决方法:ASCII编码。见下文。
NUL字符删除
没有理智的Bash方法将NUL字符存储在变量中。
这会影响扩展和read
解决方案,我不知道有什么好的解决方法。
例:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
输出:
0000000 61 00 62
0000003
0000000 61 62
0000002
哈,我们的NUL不见了!
解决方法:
陷阱的解决方法
将文件的uuencode base64编码版本存储在变量中,并在每次使用前进行解码:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
输出:
0000000 61 00 0a
0000003
uuencode和udecode是POSIX 7,但默认情况下不在Ubuntu 12.04中(sharutils
程序包)... <()
除写入另一个文件外,我看不到bash进程替换扩展的POSIX 7替代品...
当然,这很慢且不方便,所以我想真正的答案是:如果输入文件中可能包含NUL字符,请不要使用Bash。
cat
$(<someFile)