Shell标准输入和输出
来源 | OSCHINA 社区
作者 | 博学谷狂野架构师
原文链接:https://my.oschina.net/jiagoushi/blog/5609783
1 、从文件获取输入
$ wc < my.file
2、将数据与脚本存放在一起
# 下面是here-document
grep $1 <<EOF
mike x.123
joe x.234
sue x.555
pete x.818
sara x.822
bill x.919
EOF
当我们运行此脚本,可以传入一个参数,如下调用:
$ ./ext.sh bill
# 输出以下内容
bill x.919
3、避免 here-document 中的怪异行为
# 简单地查找慷慨的捐赠人
grep $1 <<EOF
pete $100
joe $200
sam $ 25
bill $ 9
EOF
但是运行时出现了奇怪的输出:
$ ./donors.sh bill
pete bill00
bill $ 9
$ ./donors.sh pete
pete pete00
正常情况下(除非使用了转义语法),bash 手册页中是这样说的:“……here-document 的每一行都要执行参数扩展、命令替换以及算术扩展”。因此,最初的 donors 脚本中所发生的事情是捐赠额被当作 shell 变量了。例如,$100 被视为 shell 变量 $1,随后跟着两个 0。这就是为什么我们在搜索 “pete” 时,得到的是 pete00;搜索 “bill” 时,得到的是 bill00。
解决办法:
通过转义结尾标记中的任意或所有字符,修改脚本内容,关闭 here-document 内部的 shell 特性 (注意观察 EOF 位置的变化):
# 简单地查找慷慨的捐赠人
grep $1 <<'EOF'
pete $100
joe $200
sam $ 25
bill $ 9
EOF
尽管其中存在非常微妙的区别,但也可以将 <<EOF 替换成 <<\EOF 或 <<'EOF',甚至是 <<E\OF,都没问题。尽管这并不是最优雅的语法,但足以告诉 bash 你希望区别处理 here-document 中的内容。如果我们转义了 EOF 的部分或全部字符,那么 bash 就知道不用执行扩展,这样就符合我们的预期行为了。
$ ./donors.sh pete
pete $100
4、获取用户输入
$ read
或者
$ read -p "answer me this " ANSWER
不带参数的 read 语句会读取用户输入并将其保存在 shell 变量 REPLY 中,这是 read 的最简形式。如果希望 bash 在读取用户输入前先输出提示信息,可以使用 -p 选项。-p 之后的单词就是提示信息,如果想提供多个单词,可以将其引用起来。记住,要在提示信息结尾处加上标点符号或空格,因为光标会停在那里等待输入。-t 选项可以设置超时值。指定秒数达到后,不管用户是否输入,read 语句都会返回。我们的示例同时用到了 -t 和 -p 选项,但你也可以单独使用 -t 选项。
上面的方式获取用户输入时会以明文回显,那适用密码输入么?
当我们需要用户输入敏感信息时,需要禁止用户输入内容的回显。此时用 read 命令读取用户输入,需要加上一个特殊选项来关闭回显:
read -s -p "password: " PASSWD
printf "%b" "\n"
-s 选项告诉 read 命令不要回显输入的字符(s 代表 silent),-p 选项指明下一个参数是提示信息,会在读取用户输入之前显示。从用户那里读取到的输入行保存在变量 $PASSWD 中。在 read 之后,我们用 printf 输出了一个换行符。这里的 printf 不能少,因为 read -s 会关闭字符回显。如果禁止了回显功能,当用户按下回车键时,就不会回显换行符,后续输出就会和提示信息出现在同一行。输出换行符会将光标带到下一行。
当然,我们也可以选择一行,如下:
read -s -p "password: " PASSWD ; printf "%b" "\n"
Shell 标准输出
软件开发人员是否要针对各种输出设备编写代码,甚至包括尚未发明的设备?
写到哪个文件?程序怎么知道是该写入代表终端窗口的文件、磁盘文件还是其他种类的文件?
1、输出到终端 / 终端窗口
echo Please wait.
输出:
Please wait.
首先,shell 负责解析 echo 的命令行参数。将参数交给 echo 前,shell 会完成所有的替换、通配符匹配等操作。
其次,在解析参数时,参数之间的空白字符会被忽略,如下图:
保留输出中的空白字符。将字符放入引号中就可以保留空白字符,如下图:
2、在输出中加入更多格式控制
printf '%s = %d\n' Lines $LINES
Lines = 24
或者:
$ printf '%-10.10s = %4.2f\n' 'Gigahertz' 1.92735
Gigahertz = 1.93
3、消除输出中的换行符
printf "%s %s" next prompt
$ echo -n prompt
$ echo -e 'hi\c'
4、保存命令输出
$ echo fill it up
fill it up
$ echo fill it up > file.txt
$ cat file.txt
fill it up
cat first.half second.half > mergeFile.txt
5、将输出保存到其他文件
echo some more data > /tmp/echo.out
或者:
echo some more data > ../../over.here
6、将输出和错误消息发送到不同文件
$ myprogram 1> messages.out 2> message.err
或者采用更常见的方法:
$ myprogram > messages.out 2> message.err
1 代表标准输出(STDOUT),
2 代表标准错误(STDERR)。
0 代表标准输入(STDIN)。
7、将输出和错误消息发送到同一文件
$ myprogram >& outfile
或者:
$ myprogram &> outfile
又或者老式且略烦琐的写法:
$ myprogram > outfile 2>&1
8、追加输出
$ ls > /tmp/ls.out
$ cd ../elsewhere
$ ls >> /tmp/ls.out
$ cd ../anotherdir
$ ls >> /tmp/ls.out
ls >> /tmp/ls.out 2>&1
在 bash 4 中,你可以将这两个重定向合二为一:
$ ls &>> /tmp/ls.out
9、丢弃输出
$ find / -name myfile 2> /dev/null
END
点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦~
微信扫码关注该文公众号作者