Linux基础之IO重定向及管道详解(涉及tr、tee命令)

本文涉及的产品
转发路由器TR,750小时连接 100GB跨地域
简介:

  什么叫IO重定向?

为了解释这个问题,我们要先明白什么叫IO,什么叫做程序的数据流。

     什么叫IO?

在Linux或计算机领域IO指的是信息的输入和输出。

在Linux中可用于输入的设备:文件(Linux中一切皆文件)

具体包括:键盘设备、文件系统上的常规文件、网卡等。

在Linux中用于输出的设备:文件

具体包括:显示器、文件系统上的常规文件、网卡等。

    什么叫做数据流?

我们通常描述的信息本质上来说都是数据,因为信息处于动态,我们就将信息或者命令等概念称作流动的数据也就是数据流。

数据流分为输入流(InputStream)和输出流(OutputStream)两类。输入流只能读不能写,而输出流只能写不能读。通常程序中使用输入流读出数据,输出流写入数据,就好像数据流入到程序并从程序中流出。采用数据流使程序的输入输出操作独立与相关设备。输入流可从键盘或文件中获得数据,输出流可向显示器、打印机或文件中传输数据。

    在Linux中,程序的数据流有三种:

输入的数据流:←标准输入 STDIN 常用设备:键盘

输出的数据流:→标准输出 STDOUT 常用设备:终端

错误输出流: →错误输出 STDERR 常用设备:终端

在Linux中打开一个文件,在该文件被加载完成后对于系统来说需要用一个数字表示,这个数字叫做fd:file descriptor 文件描述符。

因为Linux系统中一切皆文件,所以对应的标准输入设备,标准输出设备,错误输出设备都有其对应的fd

    标准输入:0

    标准输出:1

    错误输出:2

    IO重定向的意思就是将系统原本默认的输入输出的路径重新定向到其他文件

我知道解释到这里还是会很困惑,别着急,这个概念需要通过一定量的实验来说明。



    输出重定向

    其常用 >、 >> 、>|这三种表示

    >:覆盖输出  >>:追加输出  >|:强行覆盖

因为使用>不当会对原有的数据造成很大的影响,所以有时候我们会手动设定关闭>的特性。其命令为:

set -C禁止覆盖输出重定功能

set +C为开启覆盖输出重定向功能

不过上述命令对“>|”无效

下面以具体实验来说明上面内容

实验环境:在/test/目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@localhost  test ] # ll
总用量 0
[root@localhost  test ] # echo $(date) > t1
[root@localhost  test ] # ll
总用量 4
-rw-r--r--. 1 root root 43 8月   2 18:15 t1
[root@localhost  test ] # cat t1
2016年 08月 02日 星期二 18:15:28 CST
[root@localhost  test ] # echo test > t1
[root@localhost  test ] # cat t1
test
[root@localhost  test ] # echo $(who) >> t1
[root@localhost  test ] # cat t1
test
root :0 2016-08-02 10:12 (:0) root pts /0  2016-08-02 10:12 (192.168.85.1) root pts /1  2016-08-02 10:19 (192.168.85.1)
[root@localhost  test ] # set -C
[root@localhost  test ] # echo 111 > t1
- bash : t1: 无法覆盖已存在的文件
[root@localhost  test ] # echo 111 >| t1
[root@localhost  test ] # cat t1
111

上面的结果显示了>、>>、>|三者的各自功能

相信看到这里对于输入重定向会有了进一步的认识。



    错误输出流重定向 

    2> 2>>

1
2
[root@localhost  test ] # echoo 1 > t2
bash : echoo: 未找到命令...

当命令错误时,shell会返回错误信息,若我们想将错误信息存到某个文件则可按如下操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost  test ] # echoo 1 2> t2
- bash : t2: 无法覆盖已存在的文件
[root@localhost  test ] # ll
总用量 4
-rw-r--r--. 1 root root 4 8月   2 18:18 t1
-rw-r--r--. 1 root root 0 8月   2 18:20 t2
[root@localhost  test ] # echoo 1 2> t3
[root@localhost  test ] # cat t3
bash : echoo: 未找到命令...
[root@localhost  test ] # echop wqew 2>>t3
[root@localhost  test ] # cat t3
bash : echoo: 未找到命令...
相似命令是:  'echo'
bash : echop: 未找到命令...

错误重定向也支持追加。

如果我们不管命令对错都想记录那么可以使用如下格式实现:

1、&>、 &>>

1
2
3
4
5
[root@localhost  test ] # ech2 &>> t4
[root@localhost  test ] # echo right &>> t4
[root@localhost  test ] # cat t4
bash : ech2: 未找到命令...
right

2、command > /path/somewhere ... 2>&1 ;command >> /path/somewhere ... 2>&1 第二种只能为此种格式,不管前面是追加还是覆盖后面均为2>&1。2>>&1为错误格式,使用后在centos7.2下会报错。

1
2
3
4
5
[root@localhost  test ] # ech2 >> t5 2>&1      
[root@localhost  test ] # echo right >> t5 2>&1
[root@localhost  test ] # cat t5
bash : ech2: 未找到命令...
right

注:输出重定向的对象可以是各种文件,但不能将其定向至命令的输入,要想实现这个功能则需要用管道。这里大家可能有点迷,下面以例子说明

1
2
3
4
5
6
7
[root@localhost  test ] # who > tr a-z A-Z > t6
[root@localhost  test ] # cat t6
root     pts /0         2016-08-02 10:12 (192.168.85.1)
[root@localhost  test ] # ll
总用量 4
-rw-r--r--. 1 root root 54 8月   2 18:53 t6
-rw-r--r--. 1 root root  0 8月   2 18:53  tr

我们将who显示的命令重定向至tr命令的输入,之后将内容小写转换为大写后再重定向至t6文件。我们想实现的是这个结果,但是并没有实现,反而在过程中出现了tr这个文件。这是因为在第一层的重定向中,默认将tr当做文件名,但是奇怪的是tr内什么都没有,所以这种错误的理解尽早摆脱。

1
2
[root@localhost  test ] # cat tr 
[root@localhost  test ] #

我们可以使用管道完美解决上面的问题。

1
2
3
4
5
[root@localhost  test ] # who | tr a-z A-Z > t6
[root@localhost  test ] # cat t6
ROOT     :0           2016-08-02 10:12 (:0)
ROOT     PTS /0         2016-08-02 10:12 (192.168.85.1)
ROOT     PTS /1         2016-08-02 10:19 (192.168.85.1)

什么是管道,我相信通过上面的例子大家应该对它有了个初步的认知。


管道:连接程序,实现将前一个命令的输出直接定向后一个程序当做输入数据流。

其常用表达格式如下:  COMMAND1 | COMMAND2 | COMMAND3 |...

它是输出重定向的补充与加强,其本质还是类属于输出重定向。

既然说道管道,这里再多补充点

常用于管道的命令:

tee

tee - read from standard input and write to standard output and files

      显示标准输入的结果并将其写入文件

    tee的使用格式:

    命令1 | tee 文件名| 命令2

把命令1的STDOUT保存在文件名中,然后管道输入给命令2

作用:

    保存不同阶段的输出

    复杂管道的故障排除

    同时查看和记录输出

下面通过一个简单的例子说明tee的具体作用

1
2
3
4
5
6
7
8
[root@localhost  test ] # who | tee t2 | tr a-z A-Z
ROOT     :0           2016-08-02 10:12 (:0)
ROOT     PTS /0         2016-08-02 10:12 (192.168.85.1)
ROOT     PTS /1         2016-08-02 10:19 (192.168.85.1)
[root@localhost  test ] # cat t2
root     :0           2016-08-02 10:12 (:0)
root     pts /0         2016-08-02 10:12 (192.168.85.1)
root     pts /1         2016-08-02 10:19 (192.168.85.1)

tee可以将前一个的结果记录在t2文件内,同时显示后一个命令的结果。




    输入重定向

     < 单行模式、 << 多行模式

要了解输入重定向,我们得先了解一个命令

tr

 tr - translate or delete characters 转换或删除字符

其表达格式如下:

    tr[OPTION]... SET1 [SET2]

选项:

    -c或——complerment:取字符集的补集

    -d或——delete:删除所有属于第一字符集的字符

    -s或—squeeze-repeats:把连续重复的字符以单独一个字符表示

下面我们通过一个例子简要了解下tr的作用

1
2
3
4
5
6
7
8
[root@localhost  test ] # cat t1
root     :0           2016-08-02 10:12 (:0)
root     pts /0         2016-08-02 10:12 (192.168.85.1)
root     pts /1         2016-08-02 10:19 (192.168.85.1)
[root@localhost  test ] # tr a-z A-Z < t1
ROOT     :0           2016-08-02 10:12 (:0)
ROOT     PTS /0         2016-08-02 10:12 (192.168.85.1)
ROOT     PTS /1         2016-08-02 10:19 (192.168.85.1)

t1是上面tee存储的who内容,我们通过输入重定向将其作为tr的输入,并由小写转换为大写。

输入重定向就是将原来用键盘输入的内容通过其他文本内容或文件内容代替。

我想大家对于<<多行重定向有些不理解,这里再对多行重定向在以例子说明一下。

1
2
3
4
5
6
7
8
[root@localhost ~] # tr a-z A-Z << end
> morning,boys
> today is another day
> please be happy
> end
MORNING,BOYS
TODAY IS ANOTHER DAY
PLEASE BE HAPPY

多行输入重定向后面需要接规定的结尾字符串,通常使用eof或end为结尾标示符。

多行输入重定向需要手动键入内容。单行输入重定向则需要跟文件或前一个命令的输出结果。



我知道看到这里依然会有点懵,下面通过9个实例来综合使用标准输出输入及管道命令

实验环境CentOS7.2


1、将/etc/issue文件中的内容转换为大写后保存至/test/issue#文件中

1
2
3
4
5
6
7
[root@localhost  test ] # cat /etc/issue | tr a-z A-Z > /test/issue1
[root@localhost  test ] # echo $(tr a-z A-Z < /etc/issue) > /test/issue2
[root@localhost  test ] # cat issue1
\S
KERNEL \R ON AN \M
[root@localhost  test ] # cat issue2
\S KERNEL \R ON AN \M

上面两种方式均可以实现要求,只不过输出格式略有不同,这根命令有关。在没有进一步的限制下,这两种表达方式均可。第一种使用管道,输出重定向,第二种使用命令引用,输入重定向及输出重定向。


2、将当前系统登录用户的信息转换为大写后保存至/test/t2文件中

1
2
3
4
5
[root@localhost  test ] # who | tr a-z A-Z > /test/t2
[root@localhost  test ] # cat t2
ROOT     :0           2016-08-02 10:12 (:0)
ROOT     PTS /0         2016-08-02 10:12 (192.168.85.1)
ROOT     PTS /1         2016-08-02 10:19 (192.168.85.1)


3、一个linux用户给root发邮件,要求邮件标题为”help”,邮件正文如下:

Hello, I am 用户名,the system version is here,pleasehelp me to check it ,thanks!

操作系统版本信息

我们使用用户gentoo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@localhost ~] # su gentoo
[gentoo@localhost  /root ]$  whoami
gentoo
[gentoo@localhost  /root ]$  cd  /home/gentoo/
[gentoo@localhost gentoo]$  echo  -e  "Hello,I am `whoami`\nThe system version is here,please help me to check it ,thanks.\nThe version is `cat /etc/redhat-release`"  | mail -s  "help"  root   
[gentoo@localhost gentoo]$  exit
exit
您在  /var/spool/mail/root  中有新邮件
[root@localhost ~] # mail
Heirloom Mail version 12.5 7 /5/10 .  Type ?  for  help.
"/var/spool/mail/root" : 3 messages 1 new
     1 gentoo@localhost.loc  Tue Aug  2 09:38  21 /731    "help"
     2 root                  Tue Aug  2 09:44  21 /741    "help"
>N  3 gentoo@localhost.loc  Tue Aug  2 19:37  20 /737    "help"
& 3
Message  3:
From gentoo@localhost.localdomain  Tue Aug  2 19:37:36 2016
Return-Path: <gentoo@localhost.localdomain>
X-Original-To: root
Delivered-To: root@localhost.localdomain
Date: Tue, 02 Aug 2016 19:37:36 +0800
To: root@localhost.localdomain
Subject: help
User-Agent: Heirloom mailx 12.5 7 /5/10
Content-Type: text /plain ; charset=us-ascii
From: gentoo@localhost.localdomain
Status: R
-e Hello,I am gentoo
The system version is here,please help me to check it ,thanks.
The version is CentOS Linux release 7.2.1511 (Core)

这里使用了命令替换来显示用户及版本信息,管道将第一个命令的输出递给下一个命令作为其输入。


4、将/root/下文件列表,显示成一行,并文件名之间用空格隔开

1
2
[root@localhost  test ] # ls -1 /root | tr '\n' ' '\n
anaconda-ks.cfg CST dead.letter  file  initial-setup-ks.cfg  test .txt  tr  公共 模板 视频 图片 文档 下载 音乐 桌面 [root@localhost  test ] #

上面命令已经满足我们的要求了,只不过不换行看着有些别扭,下面我们在完善下使其输出看着更舒服些。

1
2
3
[root@localhost  test ] # echo -e `ls -1 /root/ | tr '\n' ' '\n` 
anaconda-ks.cfg CST dead.letter  file  initial-setup-ks.cfg  test .txt  tr  公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost  test ] #

使用echo的-e开启转义符使换行\n生效。


5、file1文件的内容为:”1 2 3 4 5 6 7 8 9 10” 计算出所有数字的总和

1
2
3
4
5
[root@localhost  test ] # cat > file1
1 2 3 4 5 6 7 8 9 10
^C
[root@localhost  test ] # cat file1 
1 2 3 4 5 6 7 8 9 10

先创建file1文件夹并输入题目要求内容。

1
2
[root@localhost  test ] # cat file1 | tr ' ' '+' | bc
55


6、处理字符串“xt.,l 1 jr#!$mn2 c*/fe3  uz4”,只保留其中的数字和空格

1
2
[root@localhost  test ] # echo 'xt.,l 1 jr#!$mn2 c*/fe3  uz4' | tr -cd '[:digit:][:space:]'
  1 2 3  4

这里使用了tr中的-c及-d补集跟删除,灵活使用补集概念可以更准确的帮助我们过滤不需要的信息。


7、将PATH变量每个目录显示在独立的一行

1
2
3
4
5
6
7
8
[root@localhost  test ] # echo ${PATH}
/usr/local/sbin : /usr/local/bin : /usr/sbin : /usr/bin : /root/bin
[root@localhost  test ] # echo ${PATH} | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin

这个题很简单只需要将PATH正确显示出来,使用tr将:替换为换行即可


8、删除指定文件的空行

这里我们创建一个含有很多空行的文本文件t9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@localhost  test ] # cat t9
q
 
 
 
ere
s
 
 
 
df
sd
 
 
 
 
sd
[root@localhost  test ] # cat t9 | tr -s '\n' 
q
ere
s
df
sd
sd

这里使用了tr的重复删除-s选项。


9、将文件中每个单词(字母)显示在独立的一行,并无空行

这里我们选择/etc/rc.d/rc0.d/K50netconsole文件,使用head查看下其文件前5行都什么内容

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost  test ] # head -5 /etc/rc.d/rc0.d/K50netconsole 
#!/bin/bash
# netconsole    This loads the netconsole module with the configured parameters.
#
# chkconfig: - 50 50
[root@localhost  test ] # cat /etc/rc.d/rc0.d/K50netconsole | tr -cs '[:alpha:]' '\n' | head -5
 
bin
bash
netconsole
This

从结果来看我们实现了题目的要求,不过为什么第一行是空行,这是因为-s是将所有的空行压缩为一行,因此前面会留有一行空行。










本文转自 紫色的茶碗 51CTO博客,原文链接:http://blog.51cto.com/chawan/1833685,如需转载请自行联系原作者
目录
相关文章
|
9天前
|
Linux
Linux 常用文件查看命令
`cat` 命令用于连接文件并打印到标准输出,适用于快速查看和合并文本文件内容。常用示例包括:`cat file1.txt` 查看单个文件,`cat file1.txt file2.txt` 合并多个文件,`cat &gt; filename` 创建新文件,`cat &gt;&gt; filename` 追加内容。`more` 和 `less` 命令用于分页查看文件,`tail` 命令则用于查看文件末尾内容,支持实时追踪日志更新,如 `tail -f file.log`。
30 5
Linux 常用文件查看命令
|
1月前
|
Linux
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
82 24
Linux系统之whereis命令的基本使用
|
15天前
|
Linux
Linux od命令
本文详细介绍了Linux中的 `od`命令,包括其基本语法、常用选项和示例。通过这些内容,你可以灵活地使用 `od`命令查看文件内容,提高分析和调试效率。确保理解每一个选项和示例的实现细节,应用到实际工作中时能有效地处理各种文件查看需求。
45 19
|
26天前
|
缓存 Ubuntu Linux
Linux中yum、rpm、apt-get、wget的区别,yum、rpm、apt-get常用命令,CentOS、Ubuntu中安装wget
通过本文,我们详细了解了 `yum`、`rpm`、`apt-get`和 `wget`的区别、常用命令以及在CentOS和Ubuntu中安装 `wget`的方法。`yum`和 `apt-get`是高层次的包管理器,分别用于RPM系和Debian系发行版,能够自动解决依赖问题;而 `rpm`是低层次的包管理工具,适合处理单个包;`wget`则是一个功能强大的下载工具,适用于各种下载任务。在实际使用中,根据系统类型和任务需求选择合适的工具,可以大大提高工作效率和系统管理的便利性。
131 25
|
25天前
|
缓存 Linux
Linux查看内存命令
1. free free命令是最常用的查看内存使用情况的命令。它显示系统的总内存、已使用内存、空闲内存和交换内存的总量。 free -h • -h 选项:以易读的格式(如GB、MB)显示内存大小。 输出示例: total used free shared buff/cache available Mem: 15Gi 4.7Gi 4.1Gi 288Mi 6.6Gi 9.9Gi Swap: 2.0Gi 0B 2.0Gi • to
36 2
|
2月前
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
69 11
|
3月前
|
Linux
linux查看目录下的文件夹命令,find查找某个目录,但是不包括这个目录本身?
通过本文的介绍,您应该对如何在 Linux 系统中查看目录下的文件夹以及使用 `find` 命令查找特定目录内容并排除该目录本身有了清晰的理解。掌握这些命令和技巧,可以大大提高日常文件管理和查找操作的效率。 在实际应用中,灵活使用这些命令和参数,可以帮助您快速定位和管理文件和目录,满足各种复杂的文件系统操作需求。
233 8
|
Linux
linux|管道符号
|管道符是什么:把前一个命令的输出结果输出给下一个命令使用。 为什么有管道符:对结果进行过滤。 使用方法: image.png 总结: image.png
990 0
|
4月前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
462 8
|
4月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
1381 6