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,如需转载请自行联系原作者
目录
相关文章
|
4天前
|
缓存 监控 Linux
|
8天前
|
Linux Shell 数据安全/隐私保护
|
9天前
|
域名解析 网络协议 安全
|
2天前
|
监控 Linux
Linux常用命令-2
本文继续介绍Linux常用命令,涵盖目录操作、文件操作、系统信息和进程管理等类别。具体包括mkdir、rmdir、cp、mv、rm、touch、whereis、whatis、dmesg、free、date、cal、ps、kill、killall和top等命令的使用方法和常用参数。
25 7
|
2天前
|
Linux Shell
Linux常用命令-1
本课程要求学生熟悉Linux系统终端窗口和命令基础,掌握文件目录类、系统信息类、进程管理类及其他常用命令,学时为3-6小时。课程内容涵盖Linux命令的特点、常见命令的使用方法及其应用场景,如文件浏览、目录切换、内容显示等。建议学生逐个操作命令并及时反馈问题。
23 5
|
5天前
|
缓存 Linux 开发者
深入理解Linux命令 `autom4te`
`autom4te` 是 GNU Autotools 中不可或缺的组件,通过高效处理 M4 宏,生成配置脚本并提供强大的调试功能。了解 `autom4te` 的工作机制和常用选项,可以帮助开发者更好地编写和维护配置文件,从而提高软件项目的配置和编译效率。在实际应用中,结合 `autoconf` 等工具,`autom4te` 能够为项目的构建过程提供坚实的基础。
14 2
|
6天前
|
Linux 开发工具
linux文本管理命令
本文档介绍了Linux系统中常用的文本处理命令,包括`echo`、`cat`、`head`、`tail`、`wc`、`less`、`grep`以及重定向符号的使用方法和练习题。此外,还详细讲解了VIM编辑器的特点、工作模式、常用快捷键和高级技巧,帮助用户高效地进行文本编辑和处理。
23 4
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
4月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
2月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
下一篇
无影云桌面