echo 不带参数时,默认输出一个换行符,>> 表示追加内容到文件末尾 。
添加这几个语句后,再执行 ./tinyshell.sh shfile 命令,就能处理到最后一行的 whoami,如下所示:
$ ./tinyshell.sh shfileshfiletinyshell.shshy$ cat shfilelwhoami$可以看到,执行之后,shfile 文件的最后一行 whoami 后面被追加了一个换行符,输出该文件内容,命令行提示符会换行打印 。
通常来说,在 Windows 下复制内容到新建文件,然后保存这个文件,文件的最后一行可能就不以换行符结尾 。
使用 -s 选项指定不回显用户输入在 bash 下,输入密码时,一般不会回显用户输入,而是什么都不显示 。我们可以使用 read 命令的 -s 选项模拟这个效果 。
查看 help read 对 -s 选项的说明如下:
-s具体举例如下:
do not echo input coming from a terminal
$ read -s -p "Your input will not echo: " inputYour input will not echo: $ echo $inputsure?这个例子指定了 -s 选项,不回显输入内容到终端 。用 -p 指定了提示字符串,输入内容会被保存到 input 变量 。
在输入的时候,界面上不会显示任何字符 。
回车之后,命令行提示符直接显示在同一行,由于没有回显换行符,所以没有换行 。
打印 input 变量的值,可以看到手动输入的内容是 “sure?” 。
如果需要在模拟的简易 shell 中输入密码,可以添加类似下面的代码,让输入密码时不回显,新增的代码前面用 + 来标识:
elif [ "$input" == "quit" ]; thenbreak+elif [ "$input" == "root" ]; then+read -s -p "Please input your password: " pwd+# handle password with $pwd+echo+echo "Your are root now."elsebash -c "${input}"fi这里添加了对 root 字符串的处理,先执行 read -s -p "Please input your password: " pwd 命令,提示让用户输入密码 。输入的内容不会回显,会保存在 pwd 变量中,可以根据实际需要进行处理 。
新增的第一个 echo 命令用于从 "Please input your password: " 字符串后面换行,否则会直接输出到同一行上 。
第二个 echo 命令只是打印一个提示语,可以根据实际需求改成对应的提示 。
使用 -n 选项指定读取多少个字符执行 read 命令读取标准输入,会不停读取输入内容,直到遇到换行符为止 。
如果我们预期最多只读取几个字符,可以使用 -n 选项来指定 。
查看 help read 对 -n 选项说明如下:
-n nchars即,read -n nchars 指定最多只读取 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
输入 nchars 个字符后,即使还没有遇到换行符,read 也会停止读取输入,返回读取到的内容 。
如果在输入 nchar 个字符之前,就遇到换行符,也会停止读取输入 。
使用 -n 选项并不表示一定要读取到 nchars 个字符 。
另外一个 -N 选项表示一定要读取到 nchars 个字符 。这里对 -N 选项不做说明 。
下面会在模拟的简易 shell 中实现一个小游戏,增加一点趣味性 。
这个小游戏使用 read -n 1 来指定每次只读取一个字符,以便输入字符就立刻停止读取,不需要再按回车 。
具体实现代码如下,这也是 tinyshell.sh 脚本最终版的代码:
#!/bin/bash -iif [ $# -ne 0 ]; thenfilename="$1"if test -n "$(tail "$filename" -c 1)"; thenecho >> "$filename"fielsefilename="/dev/stdin"fifunction game(){local count=0local T="T->"echo -e "NOW, ATTACK! $T"while read -s -n 1 char; docase $char in"h") ((--count)) ;;"l") ((++count)) ;;"q") break ;;esacfor ((i = 0; i < count; ++i)); doecho -n ""doneecho -ne "$Tr"doneecho}while read -ep "tinyshell> " input; doif [ "$input" == "l" ]; thenlselif [ "$input" == "quit" ]; thenbreakelif [ "$input" == "root" ]; thenread -s -p "Please input your password: " pwd# handle with $pwdechoecho "Your are root now."elif [ "$input" == "game" ]; thengameelsebash -c "${input}"fihistory -s "${input}"done < "$filename"主要改动是增加对 game 字符串的处理,输入这个字符串,会执行自定义的 game 函数 。该函数打印 T-> 字符串,像是一把剑(也许吧),然后用 read -s -n 1 char 命令指定每次只读取一个字符,且不回显 。
推荐阅读
- 完整版 Linux技巧:使用 bash function 命令自定义函数
- 如何在 Mac 上使用 pyenv 运行多个版本的 Python | Linux 中国
- 公司来位腾讯大牛,看完我构建的Spring MVC框架,甩给我一份文档
- Linux这5款微型发行版,体积小+精简,比win7运行还快,值得安装
- Linux磁盘管理超详细
- 手把手教你安装Windows 10之完整篇
- 吃完东西就犯困?科学家解释其中原因
- 看完胎压标示图后不知道如何充气了
- 5 种拆分 Linux 终端的方法
- Linux下查看进程线程数的方法
