![4725d8fc6d26ab63b70dd4ef669066c2.png](https://i-blog.csdnimg.cn/blog_migrate/e43112dfc94109ce8cd53c1c1e880c04.jpeg)
本系列文章使用 Linux bash 的 read 命令逐步模拟一个简易的 shell 效果,并实现一个小游戏,从中说明 read 命令的常见用法。
本篇文章主要说明下面的内容:
- 使用 -n 选项指定读取多少个字符
- 总结
使用 -n 选项指定读取多少个字符
执行 read 命令读取标准输入,会不停读取输入内容,直到遇到换行符为止。
如果我们预期最多只读取几个字符,可以使用 -n 选项来指定。查看 help read 对 -n 选项说明如下:
-n nchars
return after reading NCHARS characters rather than waiting for a newline, but honor a delimiter if fewer than NCHARS characters are read before the delimiter
即,read -n nchars 指定最多只读取 nchars 个字符,输入 nchars 个字符后,即使还没有遇到换行符,read 也会停止读取输入,返回读取到的内容。
如果在输入 nchar 个字符之前,就遇到换行符,也会停止读取输入。
使用 -n 选项并不表示一定要读取到 nchars 个字符,另外一个 -N 选项表示一定要读取到 nchars 个字符,
这里对 -N 选项不做说明。
下面会在模拟的简易 shell 中实现一个小游戏,增加一点趣味性。
这个小游戏使用 read -n 1 来指定每次只读取一个字符,以便输入字符就立刻停止读取,不需要再按回车。
具体实现代码如下,这也是 tinyshell.sh 脚本最终版的代码:
#!/bin/bash -iif [ $# -ne 0 ]; then filename="$1" if test -n "$(tail "$filename" -c 1)"; then echo >> "$filename" fielse filename="/dev/stdin"fifunction game(){ local count=0 local T="T->" echo -e "NOW, ATTACK! $T" while read -s -n 1 char; do case $char in "h") ((--count)) ;; "l") ((++count)) ;; "q") break ;; esac for ((i = 0; i < count; ++i)); do echo -n " " done echo -ne "$T " done echo}while read -ep "tinyshell> " input; do if [ "$input" == "l" ]; then ls elif [ "$input" == "quit" ]; then break elif [ "$input" == "root" ]; then read -s -p "Please input your password: " pwd # handle with $pwd echo echo "Your are root now." elif [ "$input" == "game" ]; then game else bash -c "${input}" fi history -s "${input}"done < "$filename"
主要改动是增加对 game 字符串的处理,输入这个字符串,会执行自定义的 game 函数。
该函数打印 T-> 字符串,像是一把剑(也许吧),然后用 read -s -n 1 char 命令指定每次只读取一个字符,且不回显。
如果输入 l 字符,则把 T-> 字符串的显示位置往右移。
输入 h 字符,则把 T-> 字符串的显示位置往左移。
看起来是一个左右移动的效果。
输入 q 字符,退出该游戏。
具体执行结果如下:
$ ./tinyshell.shtinyshell> gameNOW, ATTACK! T-> T->tinyshell>
由于没有回显输入字符,且始终在同一行显示 T-> 字符串,所以这个打印结果体现不出 T-> 字符串的移动,可以实际执行这个脚本,多次输入 l 、h 字符,就能看到具体效果,最后输入 q 字符退出游戏。
总结
至此,我们已经使用 read 命令来获取用户输入,模拟了一个简易的 shell 效果,可以执行脚本文件,可以通过上下光标键获取到 bash 的历史命令,支持输入密码不回显,还实现了一个小游戏。
总结 read 命令的使用关键点如下:
- 使用 -p 选项来打印提示字符,模拟 shell 的命令行提示符
- 使用 -e 选项在交互式 shell 中用 readline 库读取输入,可以避免输入上下光标键显示乱码
- 使用 -s 选项指定不回显输入内容,可用于输入密码、输入游戏控制按键等情况
- 使用 -n 1 选项指定只读取一个字符,输入字符立刻结束读取,可以在游戏中快速响应按键,不用按下回车才能响应
- 使用 “while read” 循环来重定向读取文件,可以逐行读取文件内容,执行相应命令,就像是执行脚本文件
PS:介绍 read 命令的系列文章完结~