linux入門系列7--管道符、重定向、環境變量

前面文章咱們學習了linux基礎命令,若是將不一樣命令組合使用則能夠成倍提升工做效率。本文將學習重定向、管道符、通配符、轉義符、以及重要的環境變量相關知識,爲後面的shell編程打下基礎。java

1、IO重定向

前文咱們已經講解了近60個linux經常使用命令,前文講解的查看當前目錄下有哪些文件的ls命令linux

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

執行命令後默認結果是輸出到電腦屏幕(顯示器)上的,可是若是咱們想讓命令執行結果保存到文件中,方便之後須要的時候能夠隨時查閱,咱們該怎麼作呢?這就要用到重定向的知識。shell

1.1 重定向概述

Linux shell重定向是指修改系統命令的默認執行方式,咱們能夠理解爲「改變輸入和輸出的方向」,分爲輸入重定向和輸出重定向。編程

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

相對程序而已,從鍵盤讀取用戶輸入數據供程序使用,也就是數據流從鍵盤到程序,這就是標準的輸入;程序運算產生的結果數據直接呈如今顯示器上,也就是數據流從程序到顯示器,這就是標準的輸出。默認的標準輸入、輸出以下圖:安全

file

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

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

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

與輸入輸出有關的文件描述符以下表:操作系統

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

Linux程序在執行任何形式的IO操做時,都是在讀取或寫入一個文件描述符。一個文件描述符只是一個和打開的文件相關聯的整數,它被扣多是一個硬盤上的普通文件、FIFO、管道、終端、鍵盤、顯示器,甚至是一個網絡鏈接。stdin、stdout、stderr默認都是打開的,在重定向的過程當中,0、一、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命令的錯誤輸出信息。若是要把上邊本來輸出到屏幕的信息直接寫入到文件中而不是顯示到屏幕,就要區別對待這兩種輸出信息。

1.2.1 輸入重定向

輸入重定向相關的符號和做用以下表

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

輸入重定向相對來講用的不多,輸入重定向的做用是將文件直接導入到命令中。/etc/passwd文件存儲了系統用戶信息,一行記錄一個用戶。如下示例演示經過輸入重定向將此文件導入到wc命令,統計用戶個數。

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

輸出重定向用到的符號和做用以下表

符號 做用
命令 1> 文件 將標準輸出重定向到文件中(清空原有文件數據),1能夠省略
命令 2> 文件 將錯誤輸出重定向到文件中(清空原有文件數據)
命令 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
...省略部份內容

接下來咱們演示清空寫入和追加寫入的區別,先經過覆蓋寫入模式向ls.txt文件(本來有ls的幫助信息內容)寫入一行數據,查看內容變化,而後再經過追加寫入模式向文件寫入一次數據,再查看文件內容的變化

[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

能夠看到覆蓋模式將清空文件原有內容,追加模式則在原有內容後面添加數據。

1.2.4 標準輸出和錯誤輸出區別

雖然都是重定向技術,不一樣命令的標準輸出和錯誤輸出仍是有區別的。若是一個命令執行成功,經過標準輸出到文件是沒有問題的,可是若是要錯誤輸出重定向到文件是不會成功的,依舊會顯示信息到屏幕。反之,若是一個命令執行失敗,經過錯誤輸出到文件是沒有問題的,可是若是要輸出到標準輸出是不會成功的,依舊會顯示到屏幕。

經過ls命令查看一個已經存在的文件,並將信息重定向到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

2、管道符

經過管道符能夠把不少命令組合起來,提升工做效率。簡言之管道符的做用就是:把前一個命令本來要輸出到屏幕的標準正常數據看成後一個命令的標準輸入。

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

  • 案例1:統計被禁止登錄系統的用戶數
[root@heimatengyun test]# grep "/sbin/nologin" /etc/passwd |wc -l
34

經過「linux入門系列5--新手必會的linux命令」介紹的grep命令匹配/etc/passwd文件中的關鍵字「/sbin/nologin」查找出被限制登錄系統的用戶,並將匹配結果輸入到wc命令,統計匹配到的行數,即爲被限制登錄系統的用戶數。

  • 案例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命令將內容中的小寫字母替換爲大寫字母。能夠看到只是對讀取後的內容進行替換,對原文件沒有影響。

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

不少時候想要快速地替換文本中的一些詞彙,若是手工替換,不免工做量巨大,尤爲是須要處理大批量內容的時候。這時tr命令就能夠派上用場,經過管道符將文本內容傳遞給它進行替換操做便可。

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

3、通配符

通配符的概念在不少語言中都存在,好比java、c#等,其做用就是模糊匹配。

假設你在電腦上存放了不少小電影,某一天忽然想看某位老師的電影做品,可是因爲文件太多以致於記不清楚電影文件的名稱了,只是依稀記得文件名包含了幾個關鍵字,這時候你怎麼快速找到對應的文件呢?

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

符號 意義
* 匹配0個和多個字符
匹配單個字符
[0-9] 匹配0~9之間的單個數字字符
[123] 匹配一、二、3這三個指定數字中的任意一個數字
[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

4、轉義符

「linux入門系列5--新手必會的linux命令」提到,人和Linux內核之間的交互是經過在shell終端中執行相關命令來實現的,爲了能更好地理解用戶的表達,除了通配符、管道符,shell解釋器還提供了特別豐富的轉義字符來處理用戶輸入的特殊數據。

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

轉義符 做用
\ 反斜槓,使後邊的一個變量變爲單純的字符串
'' 單引號,轉義其中全部的變量爲單純的字符串
"" 雙引號,保留其中的變量屬性,不進行轉義處理
`` 反引號,把其中的命令執行後返回結果
  • 案例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命令輸出,發現輸出的不是預期結果。緣由是Linux中$表示變量,$$則有特殊的做用,表示當前程序的進程ID號。這時就須要反斜槓來進行轉義,去除其特殊功能,將這個提取符轉義爲單純的文本。

[root@heimatengyun test]# echo "the price is \$$PRICE"
the price is $99
  • 案例2:將命令執行結果值賦值給變量並輸出
[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命令查看當前操做系統信息,並賦值給變量MYSYS,而後輸出變量值。更多變量相關知識將在下一篇文章中詳細介紹,此處主要掌握反引號這個轉義符。

5、環境變量

變量是計算機系統用於保存可變值的數據類型,在Linux系統中,變量名稱通常是大寫的,這是一種約定俗成的規範。直接經過變量名便可得到對應的變量值。

環境變量是一種特殊的變量,是操做系統要正常運行的前提,數百個環境變量協同工做才使得操做系統能正常爲用戶提供服務。然而咱們沒有必要去所有學習和掌握全部數百個環境變量,只須要學習一部分經常使用的便可。

5.1 查看環境變量之env命令

通常經過env命令查看環境變量名

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

用echo命令查詢環境變量值

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

Linux做爲一個多用戶多任務操做系統,可以爲每一個用戶提供獨立的工做環境,所以,一個相同的變量會由於用戶身份的不一樣而具備不一樣的值

案例:使用不一樣用戶查看HOME環境變量的值

[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,從試驗結果上看相同環境變量值倒是不同的。

注意:關於用戶切換命令su的用法,su test和su - test是有很是大區別的,若是不加-表示只是切換用戶不切換shell環境,若是加上-則表示連同shell環境一塊兒替換,此處不管是否切換shell環境,兩個不一樣用戶的$HOME值都不同。

5.2 設置環境變量之export命令

變量是由固定的變量名與用戶或系統設置的變量值兩部分註冊,所以咱們徹底能夠根據工做須要自行建立變量。

如下案例演示建立一個名稱爲$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

此時建立的變量$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是有很是大區別的,若是不加-表示只是切換用戶不切換shell環境。本例只是切換用戶到test並沒切換環境因此可使用$MYDIR,若是使用su - test 把shell環境也替換的話,將沒法使用自定義的$MYDIR環境變量。

5.3 經常使用的環境變量

下表列舉幾個重要經常使用的環境變量

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

5.4 命令執行流程

Linux系統中一切皆文件,Linux命令也不例外。當用戶執行一條命令以後,Linux系統到底發生了什麼事情呢?

簡單來講,命令在Linux中的執行分爲如下4個步驟

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

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

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

(4)系統在PATH環境變量中查找用戶輸入的命令,找到文件後執行命令。

簡單理解就是用戶經過shell輸入命令,shell解釋器查找對應的命令文件並執行命令

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

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

瞭解linux命令執行流程後,當接手一臺Linux系統後,在執行命令前先檢查PATH變量中是否有能夠的目錄,這是一個很好的習慣。

至此,已經學習了大部分Linux命令,知識積累的差很少了,下一篇文章咱們將綜合前面學到的知識,正式進入shell編程。

相關文章
相關標籤/搜索