我可以read用来捕获\n \012或 换行符吗?
定义测试函数:
f() { read -rd '' -n1 -p "Enter a character: " char &&
printf "\nYou entered: %q\n" "$char"; }
Run Code Online (Sandbox Code Playgroud)
运行函数,按Enter:
$ f;
Enter a character:
You entered: ''
Run Code Online (Sandbox Code Playgroud)
嗯。这是一个空字符串。
如何获得我的预期输出:
$ f;
Enter a character:
You entered: $'\012'
$
Run Code Online (Sandbox Code Playgroud)
我希望相同的方法能够捕获^D或\004.
如果read做不到,有什么办法解决?
要读取 1 个字符,请-N改为使用,它始终读取一个字符并且不进行$IFS处理:
read -rN1 var
Run Code Online (Sandbox Code Playgroud)
read -rn1读取一条记录最多一个字符并仍然进行$IFS处理(换行符是默认值,$IFS这解释了为什么即使您读取 NUL 分隔的记录也会得到空结果)。您可以使用它来限制您读取的记录的长度。
在您的情况下,使用 NUL 分隔的记录(使用-d ''),其工作方式与无论如何都无法在其变量中存储 NUL 字符IFS= read -d '' -rn1 var相同,因此将保留为空并返回非零退出状态。bashprintf '\0' | read -rN1 var$var
为了能够读取包括 NUL 在内的任意字符,您可以使用 shell,zsh而不是使用以下语法:
read -k1 'var?Enter a character: '
Run Code Online (Sandbox Code Playgroud)
(不需要-r或IFS=。但是请注意,从终端read -k读取(用于key;zsh 的选项早于 bash 甚至 ksh93数十年)。要从 stdin 读取,请使用)。k-k-Nread -u0 -k1
示例(此处按Ctrl+Space输入 NUL 字符):
$ read -k1 'var?Enter a character: '
Enter a character: ^@
$ printf '%q\n' $var
$'\0'
Run Code Online (Sandbox Code Playgroud)
请注意,为了能够读取一个字符,read可能必须读取多个字节。如果输入以多字节字符的第一个字节开始,它将至少再读取一个字节,因此$var如果输入包含未形成有效的字节序列,则最终可能会包含 shell 认为长度大于 1 的内容人物。
例如在 UTF-8 语言环境中:
$ printf '\xfc\x80\x80\x80\x80XYZ' | bash -c 'read -rN1 a; printf "<%q>\n" "$a" "${#a}"; wc -c'
<$'\374\200\200\200\200X'>
<6>
2
$ printf '\xfc\x80\x80\x80\x80XYZ' | zsh -c 'read -u0 -k1 a; printf "<%q>\n" $a $#a; wc -c'
<$'\374'$'\200'$'\200'$'\200'$'\200'X>
<6>
2
Run Code Online (Sandbox Code Playgroud)
在 UTF-8 中,0xFC 是 6 字节长字符的第一个字节,其他 5 个字节意味着设置第 8 位且未设置第 7 位,但我们只提供了 4 个。read额外的内容X以尝试找到字符的末尾,$var与不形成有效字符的 5 个字节一起结束,最终每个字节都被计为一个字符。
bash内置read可以做到这一点:
read -rd $'\0' -p ... -n 1
printf '\nYou typed ASCII %02x\n' "'$REPLY"
Run Code Online (Sandbox Code Playgroud)
(这段代码不适用于多字节字符)
请注意我没有char像您那样将读取的内容放入变量中。这是因为这样做会将 IFS 中的字符从char. 使用标准 IFS,您将无法区分空格、制表符和换行符。
| 归档时间: |
|
| 查看次数: |
9846 次 |
| 最近记录: |