Shell标准输入和输出

无论是要交给程序处理的数据,还是控制脚本的简单命令,都少不了输入和输出。程序要做的第一件事就是处理如同一阴一阳的 “输入与输出”。
1 、从文件获取输入
当我们希望向文件输出内容时,我们可以通过符号 > 或 >> 实现。而用代表输入重定向的符号 < 可以从文件中读取数据,如下:
$ wc < my.file之所以选择这种形状的操作符号,原因在于它们可以从视觉上提示重定向的方向。 很多 shell 命令可以接受一个或多个文件名作为参数,但如果没有给出文件名,命令就会从标准输入读取。使用这种命令时,可以采用 command filename 或者 command < filename,这两种形式的结果没什么区别。在这个例子中,wc 是这样,换作 cat 或其他命令,也是如此。  
2、将数据与脚本存放在一起
< 可以从文件读取数据,当你需要获得脚本输入,但又不想用单独的文件时,使用 <<(here-document)从命令行而非文件重定向输入文本。如果放在 shell 脚本中,则脚本文件可以同时包含数据与代码。 以下是名为 ext.sh 的 shell 脚本示例:
# 下面是here-documentgrep $1 < 当我们运行此脚本,可以传入一个参数,如下调用:
$ ./ext.sh bill# 输出以下内容bill x.919grep 命令查找第一个参数是否在指定文件中出现,如果没有指定文件,那么它会在标准输入中查找。通过设置 here document,告诉 shell 将标准输入重定向(临时)到此处。<< 语法表示我们想创建一个临时输入源,eof 是一个任意的字符串(你想用什么都行),用作临时输入的终止符。它并不属于输入的一部分,只是作为标记告诉输入在哪里结束。  
3、避免 here-document 中的怪异行为
here-document 在使用时可能会出现一些怪异的行为。你想用上一节介绍的方法来保存一份简单的捐赠人列表,因此创建了一个名为 donors.sh 的文件,如下所示:
# 简单地查找慷慨的捐赠人grep $1 < 但是运行时出现了奇怪的输出:
$ ./donors.sh billpete bill00bill $ 9$ ./donors.sh petepete pete00  
正常情况下(除非使用了转义语法),bash 手册页中是这样说的:“……here-document 的每一行都要执行参数扩展、命令替换以及算术扩展”。因此,最初的 donors 脚本中所发生的事情是捐赠额被当作 shell 变量了。例如,$100 被视为 shell 变量 $1,随后跟着两个 0。这就是为什么我们在搜索 “pete” 时,得到的是 pete00;搜索 “bill” 时,得到的是 bill00。
解决办法:
通过转义结尾标记中的任意或所有字符,修改脚本内容,关闭 here-document 内部的 shell 特性 (注意观察 eof 位置的变化):
# 简单地查找慷慨的捐赠人grep $1 <<'eof'pete $100joe $200sam $ 25bill $ 9eof  
尽管其中存在非常微妙的区别,但也可以将 <$ echo fill it upfill it up$ echo fill it up > file.txt我们来查看一下文件 file.txt 的内容,看看其中是否包含了命令的输出:$ cat file.txtfill it up示例第一部分的第一行中出现的 echo 命令包含了 3 个要输出的参数。第二行用 > 将这些输出保存到文件 file.txt 中,这就是看不 到 echo 输出的原因。 示例第二部分用 cat 命令显示文件内容。我们可以看出,文件中包含的正是 echo 本该输出的内容。 cat 命令得名自一个较长的单词 concatenation(拼接)。该命令会将出现在命令行上的文件的输出拼接在一起,如果你输入 cat file1 file2 file3,那么这些文件的内容会逐个发送到终端窗口。如果一个大文件被分成了两半,你也可以用 cat 将其恢复原样(也就是将两部分拼接起来),这只需将输出保存到另一个文件中:cat first.half second.half > mergefile.txt  
5、将输出保存到其他文件
如想要用重定向将输出保存到当前目录之外的其他位置,重定向输出时加上路径,如下:
echo some more data > /tmp/echo.out  
或者:
echo some more data > ../../over.here出现在重定向符号(>)后的文件名其实就是路径名。如果没有任何限定部分,那么文件就会放置在当前目录中。 如果文件名以斜线(/)起始是绝对路径名,此时文件会被放置在文件系统层次结构(目录树)中以根目录起始的指定位置。 第二个例子中,我们使用了相对路径名 ../../over.here,其中的.. 是一个指向父目录的特殊目录,存在于每个目录中。  
6、将输出和错误消息发送到不同文件
希望获得程序的输出,但不想输出被出现的错误消息弄乱。要保存的错误消息混杂在程序输出中不容易找出,可将输出和错误消息重定向到不同文件,如下:
$ myprogram 1> messages.out 2> message.err  
或者采用更常见的方法:
$ myprogram > messages.out 2> message.errshell 会创建两个输出文件。 第一个是 messages.out,程序 myprogram 的所有输出都会重定向到该文件。 第二个是 message.err,程序 myprogram 的所有错误消息都会重定向到 message.err。 在 1> 和 2> 中,数字表示文件 描述符。  
1 代表标准输出(stdout),
2 代表标准错误(stderr)。
0 代表标准输入(stdin)。
如果不指定数字,则假定为 stdout。
7、将输出和错误消息发送到同一文件
利用重定向,我们可以将输出或错误消息保存到单独的文件中,但如何将两者送往同一文件呢?用 shell 语法将标准错误消息重定向到和标准输出相同的地方。 首选:
$ myprogram >& outfile  
或者:
$ myprogram &> outfile  
又或者老式且略烦琐的写法:
$ myprogram > outfile 2>&1其中,myprogram 是准备向 stderr 和 stdout 生成输出的程序。 &> 和 >& 只是将 stdout 和 stderr 发送到相同地方的便捷写法。  
8、追加输出
每次重定向输出,都会产生一个全新的输出文件。如果想要两次(或三次、四次……)重定向输出,同时又不想破坏之前的输出,该怎么办呢? 在 bash 的重定向符号中,双大于号(>>)表示追加输出:
$ ls > /tmp/ls.out$ cd ../elsewhere$ ls >> /tmp/ls.out$ cd ../anotherdir$ ls >> /tmp/ls.out如果存在同名文件,第一行中的重定向会将其截断,并将 ls 命令的输出保存在这个已被清空的文件中。 后两次调用 ls 时使用了双大于号(>>),表示向输出文件中追加内容,而不是覆盖其原有内容。 如果想要同时重定向错误消息(stderr),可以将 stderr 的重定向放在后面,如下所示:ls >> /tmp/ls.out 2>&1  
在 bash 4 中,你可以将这两个重定向合二为一:
$ ls &>> /tmp/ls.out该命令会重定向 stderr 和 stdout,并将两者追加到指定文件中。& 符号必须先出现,且这 3 个字符之间不能有空格  
9、丢弃输出
你有时不想将输出保存到文件中或者有时甚至不想看到输出。如我们在查找某个文件时,忽略那些没有权限的提示,如下图:
此时,我们可以将输出重定向到 /dev/null,如下所示:
$ find / -name myfile 2> /dev/null其实,你可以将不想要的输出重定向到文件,然后再将其删除。但还有一个更简单的方法。unix 和 linux 系统都存在一个特殊设备,该设备并非真实的硬件,而仅仅是一个位桶(bit bucket),我们可以将不需要的数据都扔进去。它就是 /dev/null,非常适用于此类场景。写入其中的数据会被直接丢弃并不会占用磁盘空间,重定向很容易做到这一点。示例中,只有发往标准错误的输出被丢弃了  


高端汽车中高端应用所需的性能和带宽
硅谷引发通信业剧变,欧洲已被抛弃?
江苏首条实现5G网络覆盖的过江隧道
大疆创新当日在英特尔2018年智慧教育峰会上推出Tello Edu教育编程无人机
交流电机工作原理动画
Shell标准输入和输出
变压器为什么不能使直流电变压?
全局快门图像传感技术满足动态视觉市场不断演变的需求
欧司朗发布本财年第二季度财报
编程就要从娃娃抓起,启蒙型编程教育机器人——“萌新编程号”面世
A/D转换器的基本原理及种类
RAM分为简单双口RAM和真双口RAM
CPU S7-1500运动控制的操作原理
如何进行电源老化测试—吉时利数采DAQ6510
飞机上WiFi单元是什么样的?
如何为工业自动化应用选择高度准确和可靠的传感器
反相器,反相器是什么意思
行程开关的作用
宽带那点儿事(二):运营商的苦与乐
分析2020年太阳能电池市场现状及发展趋势