歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> 學習Linux >> Linux基礎知識之IO重定向及管道詳解(關於tr、tee命令)

Linux基礎知識之IO重定向及管道詳解(關於tr、tee命令)

日期:2017/3/6 9:23:37   编辑:學習Linux

Linux基礎知識之IO重定向及管道詳解(關於tr、tee命令)


Linux基礎知識之IO重定向及管道詳解(關於tr、tee命令)


我在剛開始接觸IO重定向時,經歷了由懂到不懂然後了然的過程,當然現在的我也不可能說對於IO重定向就徹底懂了,只是在解決一些問題或實現某些結果時不會因為IO重定向的問題而迷惑了。

什麼叫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/目錄下

[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>

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

當命令錯誤時,shell會返回錯誤信息,若我們想將錯誤信息存到某個文件則可按如下操作
[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、&>、 &>>
[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 第二種只能為此種格式,不管前面是追加還是覆蓋後面均為2>&1。2>>&1為錯誤格式,使用後在CentOS7.2下會報錯。
[root@localhost test]# ech2 >> t5 2>&1
[root@localhost test]# echo right >> t5 2>&1
[root@localhost test]# cat t5
bash: ech2: 未找到命令...
right

注:輸出重定向的對象可以是各種文件,但不能將其定向至命令的輸入,要想實現這個功能則需要用管道。這裡大家可能有點迷,下面以例子說明

[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內什麼都沒有,所以這種錯誤的理解盡早擺脫。
[root@localhost test]# cat tr
[root@localhost test]#

我們可以使用管道完美解決上面的問題。
[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的具體作用
[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的作用

12345678 [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的輸入,並由小寫轉換為大寫。
輸入重定向就是將原來用鍵盤輸入的內容通過其他文本內容或文件內容代替。
我想大家對於<<多行重定向有些不理解,這裡再對多行重定向在以例子說明一下。
12345678 [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#文件中
1234567 [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文件中
12345 [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
[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 [email protected] Tue Aug 2 09:38 21/731 "help"
2 root Tue Aug 2 09:44 21/741 "help"
>N 3 [email protected] Tue Aug 2 19:37 20/737 "help"
& 3
Message 3:
From [email protected] Tue Aug 2 19:37:36 2016
Return-Path: <[email protected]>
X-Original-To: root
Delivered-To: [email protected]
Date: Tue, 02 Aug 2016 19:37:36 +0800
To: [email protected]
Subject: help
User-Agent: Heirloom mailx 12.5 7/5/10
Content-Type: text/plain; charset=us-ascii
From: [email protected]
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/下文件列表,顯示成一行,並文件名之間用空格隔開
[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]#

上面命令已經滿足我們的要求了,只不過不換行看著有些別扭,下面我們在完善下使其輸出看著更舒服些。
[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” 計算出所有數字的總和
[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文件夾並輸入題目要求內容。
12 [root@localhost test]# cat file1 | tr ' ' '+' | bc
55

6、處理字符串“xt.,l 1 jr#!$mn2 c*/fe3 uz4”,只保留其中的數字和空格
[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變量每個目錄顯示在獨立的一行
[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
[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行都什麼內容
[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是將所有的空行壓縮為一行,因此前面會留有一行空行。

本文永久更新鏈接地址:

http://xxxxxx/Linuxjc/1148629.html TechArticle

Copyright © Linux教程網 All Rights Reserved