linux入門系列7--管道符、重定向、環(huán)境變量

前面文章我們學習了linux基礎命令,如果將不同命令組合使用則可以成倍提高工作效率。本文將學習重定向、管道符、通配符、轉義符、以及重要的環(huán)境變量相關知識,為后面的shell編程打下基礎。

一、IO重定向

前文我們已經(jīng)講解了近60個linux常用命令,前文講解的查看當前目錄下有哪些文件的ls命令

[root@heimatengyun test]# ls
test1.txt  test2.txt

執(zhí)行命令后默認結果是輸出到電腦屏幕(顯示器)上的,但是如果我們想讓命令執(zhí)行結果保存到文件中,方便以后需要的時候可以隨時查閱,我們該怎么做呢?這就要用到重定向的知識。

1.1 重定向概述

Linux shell重定向是指修改系統(tǒng)命令的默認執(zhí)行方式,我們可以理解為“改變輸入和輸出的方向”,分為輸入重定向和輸出重定向。

既然重定向是改變默認的輸入輸出方向,那默認的輸入輸出方向又是什么呢?

相對程序而已,從鍵盤讀取用戶輸入數(shù)據(jù)供程序使用,也就是數(shù)據(jù)流從鍵盤到程序,這就是標準的輸入;程序運算產生的結果數(shù)據(jù)直接呈現(xiàn)在顯示器上,也就是數(shù)據(jù)流從程序到顯示器,這就是標準的輸出。默認的標準輸入、輸出如下圖:

file

將默認的從鍵盤讀取數(shù)據(jù)改為從文件讀取數(shù)據(jù),也就是數(shù)據(jù)流從文件到程序,就是輸入重定向;程序運算產生的結果數(shù)據(jù)不顯示在顯示器上而是改為輸入到文件,也就是數(shù)據(jù)流從程序到文件,就是輸出重定向。

file

計算機的硬件設備有很多,常見的輸入設備有鍵盤、鼠標、麥克風、手寫板等,輸出設備有顯示器、投影儀、打印機等。 不過,在Linux中,標準輸入設備一般指鍵盤,標準輸出設備一般指顯示器。

前文提到過,Linux中一切皆文件,包括鍵盤、顯示器等輸入輸出設備在內的所有計算機硬件都是文件。為了表示和區(qū)分已經(jīng)打開的文件,Linux會為每個文件分配一個ID,這個ID是一個整數(shù),被稱為文件描述符(File Descriptor)。

與輸入輸出有關的文件描述符如下表:

文件描述符 文件名 類型 硬件
0 stdin 標準輸入文件 硬盤
1 stdout 標準輸出文件 顯示器
2 stderr 標準錯誤輸出文件 顯示器

Linux程序在執(zhí)行任何形式的IO操作時,都是在讀取或寫入一個文件描述符。一個文件描述符只是一個和打開的文件相關聯(lián)的整數(shù),它被扣可能是一個硬盤上的普通文件、FIFO、管道、終端、鍵盤、顯示器,甚至是一個網(wǎng)絡連接。stdin、stdout、stderr默認都是打開的,在重定向的過程中,0、1、2這三個文件描述符可以直接使用。

1.2 重定向分類

重定向分為輸入和輸出重定向。簡言之,輸入重定向就是把文件導入到命令,輸出重定向則是把原本要輸出到屏幕的信息寫入到指定文件中。平時工作中,相對于輸入重定向,輸出重定向使用頻率更高,因此又將輸出重定向細分為標準輸出重定向和錯誤輸出重定向,輸出重定向又分為:清空寫入和追加兩種模式。

關于標準輸出和錯誤輸出請看下面示例:

[root@heimatengyun ~]# ls test/
test1.txt  test2.txt
[root@heimatengyun ~]# ls xxx
ls: cannot access xxx: No such file or directory

用ls命令查看制定目錄下的文件信息,如果文件夾存在且文件夾下有內容將輸出文件所有者、所屬組、文件大小等信息,也就是ls命令的標準輸出信息。但是如果查看一個不存在的文件夾,則提示文件不存在的報錯信息,也就是ls命令的錯誤輸出信息。如果要把上邊原本輸出到屏幕的信息直接寫入到文件中而不是顯示到屏幕,就要區(qū)別對待這兩種輸出信息。

1.2.1 輸入重定向

輸入重定向相關的符號和作用如下表

符號 作用
命令 < 文件 將文件作為命令的標準輸入
命令 << 分界符 從標準輸入中讀入,直到遇到分解符才停止
命令 < 文件1 > 文件2 將文件1作為命令的標準輸入并將標準輸出到文件2

輸入重定向相對來說用的很少,輸入重定向的作用是將文件直接導入到命令中。/etc/passwd文件存儲了系統(tǒng)用戶信息,一行記錄一個用戶。以下示例演示通過輸入重定向將此文件導入到wc命令,統(tǒng)計用戶個數(shù)。

[root@heimatengyun test]# wc -l < /etc/passwd
39
1.2.2 輸出重定向

輸出重定向用到的符號和作用如下表

符號 作用
命令 1> 文件 將標準輸出重定向到文件中(清空原有文件數(shù)據(jù)),1可以省略
命令 2> 文件 將錯誤輸出重定向到文件中(清空原有文件數(shù)據(jù))
命令 1>> 文件 將標準輸出重定向到文件中(追加到原有內容后面),1可以省略
命令 2>> 文件 將錯誤輸出重定向到文件中(追加到原有內容后面)
命令 &>> 文件 將標準輸出和錯誤輸出共同寫入到文件中(追加到原有內容后面)
命令 >> 文件 2>&1 同上條命令:命令 &>> 文件

對于重定向中的標準輸出模式,一般省略文件描述符1不寫,而錯誤輸出模式的文件描述符2是必須要寫的。

1.2.3 輸出重定向案例

通過man命令查看ls命令的使用方法,并將輸出信息重定向到ls.txt文件中,然后就可以使用cat命令查看ls.txt文件的信息。

[root@heimatengyun test]# ls
test1.txt  test2.txt
[root@heimatengyun test]# man ls > ls.txt
[root@heimatengyun test]# ls
ls.txt  test1.txt  test2.txt
[root@heimatengyun test]# cat ls.txt 
LS(1)                           User Commands                           LS(1)
NAME
       ls - list directory contents
SYNOPSIS
       ls [OPTION]... [FILE]...
DESCRIPTION
...省略部分內容

接下來我們演示清空寫入和追加寫入的區(qū)別,先通過覆蓋寫入模式向ls.txt文件(原本有l(wèi)s的幫助信息內容)寫入一行數(shù)據(jù),查看內容變化,然后再通過追加寫入模式向文件寫入一次數(shù)據(jù),再查看文件內容的變化

[root@heimatengyun test]# echo "wellcome" > ls.txt 
[root@heimatengyun test]# cat ls.txt 
wellcome
[root@heimatengyun test]# echo "write message again" >> ls.txt 
[root@heimatengyun test]# cat ls.txt 
wellcome
write message again

可以看到覆蓋模式將清空文件原有內容,追加模式則在原有內容后面添加數(shù)據(jù)。

1.2.4 標準輸出和錯誤輸出區(qū)別

雖然都是重定向技術,不同命令的標準輸出和錯誤輸出還是有區(qū)別的。如果一個命令執(zhí)行成功,通過標準輸出到文件是沒有問題的,但是如果要錯誤輸出重定向到文件是不會成功的,依舊會顯示信息到屏幕。反之,如果一個命令執(zhí)行失敗,通過錯誤輸出到文件是沒有問題的,但是如果要輸出到標準輸出是不會成功的,依舊會顯示到屏幕。

通過ls命令查看一個已經(jīng)存在的文件,并將信息重定向到ls.txt文件,查看該文件可以看到成功存入信息。將其錯誤輸出重定向到ls-err.txt文件,由于查看的該文件存在,沒有錯誤信息所以看到查詢成功的文件信息依然顯示在了屏幕上,而錯誤重定向的文件里沒有內容。

[root@heimatengyun test]# ls
test1.txt  test2.txt
[root@heimatengyun test]# ls -l test1.txt 
-rw-r--r--. 1 root root 0 Nov 30 15:34 test1.txt
[root@heimatengyun test]# ls -l test1.txt > ls.txt
[root@heimatengyun test]# ls
ls.txt  test1.txt  test2.txt
[root@heimatengyun test]# cat ls.txt 
-rw-r--r--. 1 root root 0 Nov 30 15:34 test1.txt
[root@heimatengyun test]# ls -l test1.txt 2> ls-err.txt
-rw-r--r--. 1 root root 0 Nov 30 15:34 test1.txt
[root@heimatengyun test]# ls
ls-err.txt  ls.txt  test1.txt  test2.txt
[root@heimatengyun test]# cat ls-err.txt 

二、管道符

通過管道符可以把很多命令組合起來,提高工作效率。簡言之管道符的作用就是:把前一個命令原本要輸出到屏幕的標準正常數(shù)據(jù)當作后一個命令的標準輸入。

管道符用|表示,使用格式為:命令A|命令B|命令C...

  • 案例1:統(tǒng)計被禁止登陸系統(tǒng)的用戶數(shù)
[root@heimatengyun test]# grep "/sbin/nologin" /etc/passwd |wc -l
34

通過“l(fā)inux入門系列5--新手必會的linux命令”介紹的grep命令匹配/etc/passwd文件中的關鍵字“/sbin/nologin”查找出被限制登陸系統(tǒng)的用戶,并將匹配結果輸入到wc命令,統(tǒng)計匹配到的行數(shù),即為被限制登陸系統(tǒng)的用戶數(shù)。

  • 案例2:將文件內容中的小寫字母替換為大寫字母輸出
[root@heimatengyun test]# cat test1.txt 
wellcome
[root@heimatengyun test]# cat test1.txt |tr [a-z] [A-Z]
WELLCOME
[root@heimatengyun test]# cat test1.txt 
wellcome

通過cat命令讀取test1.txt文件內容并導入到tr命令,通過tr命令將內容中的小寫字母替換為大寫字母??梢钥吹街皇菍ψx取后的內容進行替換,對原文件沒有影響。

tr命令作用是替換文本文件中的字符,格式為:tr [原始字符] [目標字符]

很多時候想要快速地替換文本中的一些詞匯,如果手工替換,難免工作量巨大,尤其是需要處理大批量內容的時候。這時tr命令就可以派上用場,通過管道符將文本內容傳遞給它進行替換操作即可。

ps:前文講了近60個Linux命令,命令太多不可能一一涵蓋,其余的命令將根據(jù)場景需求逐步以案例的形式分散到各文中進行演示。

三、通配符

通配符的概念在很多語言中都存在,比如java、c#等,其作用就是模糊匹配。

假設你在電腦上存放了很多小電影,某一天突然想看某位老師的電影作品,但是由于文件太多以至于記不清楚電影文件的名稱了,只是依稀記得文件名包含了幾個關鍵字,這時候你怎么快速找到對應的文件呢?

通配符就是面對這種場景而生,熟練使用通配符,再多電影都不迷路。通配符顧名思義就是通用的匹配信息的符號,主要包含以下幾個:

符號 意義
* 匹配0個和多個字符
? 匹配單個字符
[0-9] 匹配0~9之間的單個數(shù)字字符
[123] 匹配1、2、3這三個指定數(shù)字中的任意一個數(shù)字
[abc] 匹配a、b、c三個字符中的任意一個字符
  • 案例1:匹配文件名以test開頭的所有文件
[root@heimatengyun test]# ls
test1.txt  test2.txt
[root@heimatengyun test]# ls -l test*
-rw-r--r--. 1 root root 9 Nov 30 20:43 test1.txt
-rw-r--r--. 1 root root 0 Nov 30 15:34 test2.txt

  • 案例2:匹配文件名最后一位為1或3的所有文件
[root@heimatengyun test]# ls
test1.txt  test2.txt
[root@heimatengyun test]# ls -l test[13].txt
-rw-r--r--. 1 root root 9 Nov 30 20:43 test1.txt

四、轉義符

“l(fā)inux入門系列5--新手必會的linux命令”提到,人和Linux內核之間的交互是通過在shell終端中執(zhí)行相關命令來實現(xiàn)的,為了能更好地理解用戶的表達,除了通配符、管道符,shell解釋器還提供了特別豐富的轉義字符來處理用戶輸入的特殊數(shù)據(jù)。

本文只抽取幾個常用的通配符進行講解,轉義符及對應的功能如下:

轉義符 作用
\ 反斜杠,使后邊的一個變量變?yōu)閱渭兊淖址?/td>
'' 單引號,轉義其中所有的變量為單純的字符串
"" 雙引號,保留其中的變量屬性,不進行轉義處理
`` 反引號,把其中的命令執(zhí)行后返回結果
  • 案例1:輸出美元$表示的價格
[root@heimatengyun test]# PRICE=99
[root@heimatengyun test]# echo "the price is $PRICE"
the price is 99
[root@heimatengyun test]# echo "the price is $$PRICE"
the price is 12395PRICE

定義PRICE變量保存價格,然后通過echo命令輸出,發(fā)現(xiàn)輸出的不是預期結果。原因是Linux中$表示變量,$$則有特殊的作用,表示當前程序的進程ID號。這時就需要反斜杠來進行轉義,去除其特殊功能,將這個提取符轉義為單純的文本。

[root@heimatengyun test]# echo "the price is \$$PRICE"
the price is $99

  • 案例2:將命令執(zhí)行結果值賦值給變量并輸出
[root@heimatengyun test]# uname -a
Linux heimatengyun 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[root@heimatengyun test]# MYSYS=`uname -a`
[root@heimatengyun test]# echo $MYSYS
Linux heimatengyun 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

用uname命令查看當前操作系統(tǒng)信息,并賦值給變量MYSYS,然后輸出變量值。更多變量相關知識將在下一篇文章中詳細介紹,此處主要掌握反引號這個轉義符。

五、環(huán)境變量

變量是計算機系統(tǒng)用于保存可變值的數(shù)據(jù)類型,在Linux系統(tǒng)中,變量名稱一般是大寫的,這是一種約定俗成的規(guī)范。直接通過變量名即可獲得對應的變量值。

環(huán)境變量是一種特殊的變量,是操作系統(tǒng)要正常運行的前提,數(shù)百個環(huán)境變量協(xié)同工作才使得操作系統(tǒng)能正常為用戶提供服務。然而我們沒有必要去全部學習和掌握所有數(shù)百個環(huán)境變量,只需要學習一部分常用的即可。

5.1 查看環(huán)境變量之env命令

一般通過env命令查看環(huán)境變量名

[root@heimatengyun test]# env
XDG_SESSION_ID=2
HOSTNAME=heimatengyun
SELINUX_ROLE_REQUESTED=
TERM=linux
SHELL=/bin/bash
...省略部分內容

用echo命令查詢環(huán)境變量值

[root@heimatengyun test]# echo $SHELL
/bin/bash

Linux作為一個多用戶多任務操作系統(tǒng),能夠為每個用戶提供獨立的工作環(huán)境,因此,一個相同的變量會因為用戶身份的不同而具有不同的值

案例:使用不同用戶查看HOME環(huán)境變量的值

[root@heimatengyun ~]# echo $HOME
/root
[root@heimatengyun ~]# su - test
Last login: Sat Nov 30 22:39:50 CST 2019 on pts/0
[test@heimatengyun ~]$ echo $HOME
/home/test
[test@heimatengyun ~]$ exit
logout
[root@heimatengyun ~]# 

案例中先使用root用戶查看HOME的值,然后切換到test用戶再次查看HOME,從試驗結果上看相同環(huán)境變量值卻是不一樣的。

注意:關于用戶切換命令su的用法,su test和su - test是有非常大區(qū)別的,如果不加-表示只是切換用戶不切換shell環(huán)境,如果加上-則表示連同shell環(huán)境一起替換,此處無論是否切換shell環(huán)境,兩個不同用戶的$HOME值都不一樣。

5.2 設置環(huán)境變量之export命令

變量是由固定的變量名與用戶或系統(tǒng)設置的變量值兩部分注冊,因此我們完全可以根據(jù)工作需要自行創(chuàng)建變量。

以下案例演示創(chuàng)建一個名稱為$MYDIR,值為/etc/profile.d/ 目錄的自定義變量,這樣我們只需要通過該變量,就可以很方便的進入到值對應的目錄。

[root@heimatengyun test]# MYDIR=/etc/profile.d/        
[root@heimatengyun test]# echo $MYDIR
/etc/profile.d/
[root@heimatengyun test]# pwd
/root/test
[root@heimatengyun test]# cd $MYDIR
[root@heimatengyun profile.d]# pwd
/etc/profile.d

此時創(chuàng)建的變量$MYDIR不具有全局性,作用范圍有限,默認情況下不能被其他用戶使用。

[root@heimatengyun ~]# su test
[test@heimatengyun root]$ echo $MYDIR

[test@heimatengyun root]$ exit
exit

可以看到切換到test用戶后,該變量沒有值,并且通過env命令查看也未查到該變量。

如果要想讓其他用戶也可以使用該變量,則需要用export命令,將其提升為全局變量。注意export命令后的變量名不加$。

[root@heimatengyun ~]# export MYDIR
[root@heimatengyun ~]# env
XDG_SESSION_ID=2
HOSTNAME=heimatengyun
SELINUX_USE_CURRENT_RANGE=
MYDIR=/etc/profile.d/
...省略部分內容

通過env命令也可以查到該變量,此時我們在切換到test用戶查看是否可以使用

[root@heimatengyun ~]# su test
[test@heimatengyun root]$ echo $MYDIR
/etc/profile.d/
[test@heimatengyun root]$ exit
exit

注意:再次強調一下,su test和su - test是有非常大區(qū)別的,如果不加-表示只是切換用戶不切換shell環(huán)境。本例只是切換用戶到test并沒切換環(huán)境所以可以使用MYDIR,如果使用su - test 把shell環(huán)境也替換的話,將無法使用自定義的MYDIR環(huán)境變量。

5.3 常用的環(huán)境變量

下表列舉幾個重要常用的環(huán)境變量

變量名稱 作用
HOME 用戶家目錄
SHELL 用戶在使用的shell解釋器名稱
HISTSIZE 輸出的歷史命令記錄條數(shù)
HISTFILESIZE 保存的歷史命令記錄條數(shù)
LANG 系統(tǒng)語言、語系名稱
PATH 定義解釋器搜索用戶執(zhí)行命令的路徑

5.4 命令執(zhí)行流程

Linux系統(tǒng)中一切皆文件,Linux命令也不例外。當用戶執(zhí)行一條命令之后,Linux系統(tǒng)到底發(fā)生了什么事情呢?

簡單來說,命令在Linux中的執(zhí)行分為以下4個步驟

(1)判斷用戶是否以絕對路徑或相對路徑的方式輸入命令,如果是則直接執(zhí)行,不是則進行第二步

(2)檢查用戶輸入的命令是否有別名命令,如果有別名找到原命令,如果無則進行第三步

(3)bash解釋器判斷用戶輸入的是內部命令還是外部命令,如是內部命令則直接執(zhí)行,外部命令則進行第四步

(4)系統(tǒng)在PATH環(huán)境變量中查找用戶輸入的命令,找到文件后執(zhí)行命令。

簡單理解就是用戶通過shell輸入命令,shell解釋器查找對應的命令文件并執(zhí)行命令。

注意:思考一下一個經(jīng)典的問題,能否將當前目錄(.)添加到環(huán)境變量PATH中呢?

盡管可以將當前目錄(.)添加到PATH變量中,使得在某些情況下可以讓用戶免去輸入命令路徑的麻煩,但是,這樣存在很大的安全風險。假如黑客在常用的公用目錄/tmp下存放一個與ls或cd等命令同名的病毒文件,而用戶恰巧又在公共目錄中執(zhí)行了這些命令,那就很可能中招了。

了解linux命令執(zhí)行流程后,當接手一臺Linux系統(tǒng)后,在執(zhí)行命令前先檢查PATH變量中是否有可以的目錄,這是一個很好的習慣。

至此,已經(jīng)學習了大部分Linux命令,知識積累的差不多了,下一篇文章我們將綜合前面學到的知識,正式進入shell編程。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容