js快速排序 物联网项目 matlotlib iic CK mobile dll outlook layer ide Plupload lazyloadjs vue原理 vue动态绑定class 后台管理界面模板 js鼠标离开事件 mysql汉化包 docker查看所有容器 matlab求向量的模 windows安装python环境 java重写和重载的区别 java中的基本数据类型 java开发环境搭建 java初级教程 java遍历集合 java创建目录 怪物猎人ol捏脸数据 彻底删除mysql 只狼脚本 迅雷去广告版 robotstudio 魔兽七个人 催眠魔蛙 文明6万神殿 小米9截屏 一键root软件下载 浣海之核 pr旋转视频 kms工具 js弹出框
当前位置: 首页 > 学习教程  > 编程语言

第四部分

2020/8/11 20:33:25 文章标签:

2020-04-04

标准输出重定向

I/O 重定向允许我们来重定义标准输出的地点。我们使用 “>” 重定向符后接文件名将标准输出重定向到除屏幕以外的另一个文件。

[root@VM_0_7_centos ~]# ls -l /usr/bin > ls-output.txt
[root@VM_0_7_centos ~]# ls -l ls-output.txt 
-rw-r--r-- 1 root root 63953 Apr  4 18:38 ls-output.txt

这里,我们创建了一个长长的目录/usr/bin 列表,并且输送程序运行结果到文件 ls-output.txt中。

[root@VM_0_7_centos ~]# ls -l /bin/usr > ls-output.txt 
ls: cannot access /bin/usr: No such file or directory
[root@VM_0_7_centos ~]# ls -l ls-output.txt 
-rw-r--r-- 1 root root 0 Apr  4 18:39 ls-output.txt

我们把目录换成一个不存在的目录。我们收到一个错误信息。这讲得通,因为我们指定了一个不存在的目录/bin/usr, 但是为什么这条错误信息显示在屏幕上而不是被重定向到文件 ls-output.txt?答案是,ls 程序不把它的错误信息输送到标准输出。反而,像许多写得不错的 Unix 程序,ls 把错误信息送到标准错误。

因为我们只是重定向了标准输出,而没有重定向标准错误,所以错误信息被送到屏幕。

先看一下我们的输出文件发生了什么事情,文件长度为零!这是因为,当我们使用 “>” 重定向符来重定向输出结果时,目标文件总是从开头被重写。因为我们 ls 命令没有产生运行结果,只有错误信息,重定向操作开始重写文件,然后由于错误而停止,导致文件内容清空。事实上,如果我们需要清空一个文件内容(或者创建一个新的空文件),可以使用这样的技巧:

[root@VM_0_7_centos ~]# > ls-output.txt 
[root@VM_0_7_centos ~]# ls -l ls-output.txt 
-rw-r--r-- 1 root root 0 Apr  4 18:44 ls-output.txt

简单地使用重定向符,没有命令在它之前,这会清空一个已存在文件的内容或是创建一个新的空文件。

使用 “>>” 操作符,将导致输出结果添加到文件内容之后。如果文件不存在,文件会被创建,就如使用了 “>” 操作符。

[root@VM_0_7_centos ~]# ls -l /usr/bin >> ls-output.txt
[root@VM_0_7_centos ~]# ls -l ls-output.txt 
-rw-r--r-- 1 root root 63953 Apr  4 18:46 ls-output.txt

我们重复执行命令三次,导致输出文件大小是原来的三倍。

标准错误重定向

标准错误重定向没有专用的重定向操作符。为了重定向标准错误,我们必须参考其文件描述符。一个程序可以在几个编号的文件流中的任一个上产生输出。虽然我们已经将这些文件流的前三个称作标准输入、输出和错误,shell 内部分别将其称为文件描述符 0、1 和 2。shell 使用文件描述符提供了一种表示法来重定向文件。因为标准错误和文件描述符 2 一样,我们用这种表示法来重定向标准错误:

[root@VM_0_7_centos ~]# ls -l /bin/usr 2> ls-error.txt
[root@VM_0_7_centos ~]# ls -l ls-error.txt 
-rw-r--r-- 1 root root 54 Apr  4 18:50 ls-error.txt
[root@VM_0_7_centos ~]# cat ls-error.txt 
ls: cannot access /bin/usr: No such file or directory

文件描述符 “2”,紧挨着放在重定向操作符之前,来执行重定向标准错误到文件 ls-error.txt任务。

重定向标准输出和错误到同一个文件

方法一(传统方法):

[root@VM_0_7_centos ~]# clear
[root@VM_0_7_centos ~]# ls -l /bin/usr > ls-output.txt 2> &1
-bash: syntax error near unexpected token `&'
[root@VM_0_7_centos ~]# ls -l /bin/usr > ls-output.txt 2>&1
[root@VM_0_7_centos ~]# 

使用这种方法,我们完成两个重定向。首先重定向标准输出到文件 ls-output.txt,然后重定向文件描述符 2(标准错误)到文件描述符 1(标准输出)使用表示法 2>&1

注意重定向的顺序安排非常重要。标准错误的重定向必须总是出现在标准输出重定向之后,要不然它不起作用。

方法二:

[root@VM_0_7_centos ~]# ls -l /bin/usr &> ls-output.txt
[root@VM_0_7_centos ~]# ls -l ls-output.txt 
-rw-r--r-- 1 root root 54 Apr  4 18:58 ls-output.txt
[root@VM_0_7_centos ~]# cat ls-output.txt 
ls: cannot access /bin/usr: No such file or directory

在这个例子里面,我们使用单单一个表示法 &> 来重定向标准输出和错误到文件 ls-output.txt

处理不需要的输出

有时候“沉默是金”,我们不想要一个命令的输出结果,只想把它们扔掉。这种情况尤其适用于错误和状态信息。系统通过重定向输出结果到一个叫做 “/dev/null” 的特殊文件,为我们提供了解决问题的方法。这个文件是系统设备,叫做位存储桶,它可以接受输入,并且对输入不做任何处理。为了隐瞒命令错误信息,我们这样做:

[root@VM_0_7_centos ~]# ls -l /bin/usr 2> /dev/null
[root@VM_0_7_centos ~]# 

Unix 文化中的/dev/null
位存储桶是个古老的 Unix 概念,由于它的普遍性,它的身影出现在 Unix 文化的许多部分。当有人说他/她正在发送你的评论到/dev/null,现在你应该知道那是什么意思了。更多的例子,可以阅读 Wikipedia 关于 “/dev/null” 的文章。

cat -连接文件

cat 命令读取一个或多个文件,然后复制它们到标准输出。
你可以使用 cat 来显示文件而没有分页,cat 经常被用来显示简短的文本文件。因为 cat 可以接受不只一个文件作为参数,所以它也可以用来把文件连接在一起。

如果 cat 没有给出任何参数,它会从标准输入读入数据,又因为标准输入默认情况下连接到键盘,它正在等待我们输入数据!

[root@VM_0_7_centos ~]# cat
This is China!This is China![root@VM_0_7_centos ~]# 

首先输入“This is China”,下一步,输入 Ctrl-d(按住 Ctrl 键同时按下 “d”),来告诉 cat,在标准输入中,它已经到达文件末尾(EOF),由于没有文件名参数,cat 复制标准输入到标准输出,所以我们看到文本行重复出现。

我们可以使用这种行为来创建简短的文本文件。

[root@VM_0_7_centos ~]# cat > lazy_dog.txt
This is China![root@VM_0_7_centos ~]# cat lazy_dog.txt 
This is China![root@VM_0_7_centos ~]# 

输入命令,其后输入要放入文件中的文本。记住,最后输入 Ctrl-d。通过使用这个命令,我们实现了世界上最低能的文字处理器!

[root@VM_0_7_centos ~]# cat < lazy_dog.txt
This is China![root@VM_0_7_centos ~]# 

使用“<”重定向操作符,我们把标准输入源从键盘改到文件 lazy_dog.tx。我们看到结果和传递单个文件名作为参数的执行结果一样。

管道线

命令从标准输入读取数据并输送到标准输出的能力被一个称为管道线的 shell 特性所利用。使用管道操作符 “|”(竖杠),一个命令的标准输出可以通过管道送至另一个命令的标准输入。

过滤器

管道线经常用来对数据完成复杂的操作。有可能会把几个命令放在一起组成一个管道线。通常,以这种方式使用的命令被称为过滤器。过滤器接受输入,以某种方式改变它,然后输出它。第一个我们想试验的过滤器是 sort。想象一下,我们想把目录/bin 和/usr/bin 中的可执行程序都联合在一起,再把它们排序,然后浏览执行结果:

ls /bin /usr/bin | sort | less

因为我们指定了两个目录(/bin 和/usr/bin),ls 命令的输出结果由有序列表组成,各自针对一个目录。通过在管道线中包含 sort,我们改变输出数据,从而产生一个有序列表。

uniq - 报道或忽略重复行

uniq 命令经常和 sort 命令结合在一起使用。uniq 从标准输入或单个文件名参数接受数据有序列表(详情查看 uniq 手册页),默认情况下,从数据列表中删除任何重复行。所以,为了确信我们的列表中不包含重复句子(这是说,出现在目录/bin 和/usr/bin 中重名的程序),我们添加 uniq 到我们的管道线中:

ls /bin /usr/bin | sort | uniq | less

在这个例子中,我们使用 uniq 从 sort 命令的输出结果中,来删除任何重复行。如果我们想看到重复的数据列表,让 uniq 命令带上 “-d” 选项,就像这样:

 ls /bin /usr/bin | sort | uniq -d | less

wc -打印行数、字数和字节数

wc(字计数)命令是用来显示文件所包含的行数、字数和字节数。例如:

[root@VM_0_7_centos ~]# wc ls-output.txt
 1  9 54 ls-output.txt
[root@VM_0_7_centos ~]# wc -l ls-output.txt
1 ls-output.txt

在这个例子中,wc 打印出来三个数字:包含在文件 ls-output.txt 中的行数,单词数和字节数,正如我们先前的命令,如果 wc 不带命令行参数,它接受标准输入。“-l” 选项限制命令输出只能报道行数。添加 wc 到管道线来统计数据,是个很便利的方法。查看我们的有序列表中程序个数,我们可以这样做:

[root@VM_0_7_centos ~]# ls /bin /usr/bin | sort | uniq | wc -l
1028

grep -打印匹配行

grep 是个很强大的程序,用来找到文件中的匹配文本。这样使用 grep 命令:

grep pattern [file...]

当 grep 遇到一个文件中的匹配 “模式”,它会打印出包含这个类型的行。

比如说,我们想在我们的程序列表中,找到文件名中包含单词 “zip” 的所有文件。这样一个搜索,可能让我们了解系统中的一些程序与文件压缩有关系。这样做:

[root@VM_0_7_centos ~]# ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
bzip2recover
funzip
gpg-zip
gunzip
...

grep 有一些方便的选项:“-i” 使得 grep 在执行搜索时忽略大小写(通常,搜索是大小写敏感的),“-v” 选项会告诉 grep 只打印不匹配的行。

head / tail -打印文件开头部分/结尾部分

head 命令打印文件的前十行,而 tail 命令打印文件的后十行。默认情况下,两个命令都打印十行文本,但是可以通过 “-n” 选项来调整命令打印的行数。

[root@VM_0_7_centos ~]# head -n 5 ls-output.txt
ls: cannot access /bin/usr: No such file or directory
...

tail 有一个选项允许你实时地浏览文件。当观察日志文件的进展时,这很有用,因为它们同时在被写入。

在以下的例子里,我们要查看目录/var/log 里面的信息文件。

[root@VM_0_7_centos ~]# tail -f /var/log/messages
Apr  4 18:00:00 VM_0_7_centos systemd: Started Docker Cleanup.
Apr  4 18:01:01 VM_0_7_centos systemd: Created slice User Slice of root.
Apr  4 18:01:01 VM_0_7_centos systemd: Started Session 468 of user root.
Apr  4 18:01:01 VM_0_7_centos systemd: Removed slice User Slice of root.
Apr  4 18:28:13 VM_0_7_centos systemd: Created slice User Slice of root.
Apr  4 18:28:13 VM_0_7_centos systemd: Started Session 469 of user root.
Apr  4 18:28:13 VM_0_7_centos systemd-logind: New session 469 of user root.
Apr  4 19:00:20 VM_0_7_centos systemd: Starting Docker Cleanup...
Apr  4 19:00:20 VM_0_7_centos systemd: Started Docker Cleanup.
Apr  4 19:01:01 VM_0_7_centos systemd: Started Session 470 of user root.
^C
[root@VM_0_7_centos ~]# 

使用 “-f” 选项,tail 命令继续监测这个文件,当新的内容添加到文件后,它们会立即出现在屏幕上。这会一直继续下去直到你输入 Ctrl-c。

tee -从 Stdin 读取数据,并同时输出到 Stdout 和文件

为了和我们的管道隐喻保持一致,Linux 提供了一个叫做 tee 的命令,这个命令制造了一个“tee”,安装到我们的管道上。tee 程序从标准输入读入数据,并且同时复制数据到标准输出(允许数据继续随着管道线流动)和一个或多个文件。当在某个中间处理阶段来捕捉一个管道线的内容时,这很有帮助。这里,我们重复执行一个先前的例子,这次包含 tee 命令,在 grep 过滤管道线的内容之前,来捕捉整个目录列表到文件 ls.txt:

[root@VM_0_7_centos ~]# ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
bzip2recover
funzip
gpg-zip
...

在执行Linux命令时,我们可以把输出重定向到文件中,比如 ls >a.txt,

这时我们就不能看到输出了,如果我们既想把输出保存到文件中,又想在屏幕上看到输出内容,就可以使用tee命令了。

tee命令读取标准输入,把这些内容同时输出到标准输出和(多个)文件中,tee命令可以重定向标准输出到多个文件。要注意的是:在使用管道线时,前一个命令的标准错误输出不会被tee读取。


本文链接: http://www.dtmao.cc/news_show_100356.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?