1. 程式人生 > >shell腳本基礎和grep使用

shell腳本基礎和grep使用

模式 for lse histsize mktemp chmod 修改 列數 n)

shell腳本基礎和grep使用

一、shell腳本基礎

(1)、命令hash

hash的作用:緩存此前命令的查找結果:key-value數據格式(鍵值),key:搜索鍵;value:值

hash的使用:

  1. 直接使用hash,列出緩存的所有命令
  2. -d選項,hash -d COMMAND:表示清空指定命令的緩存,如hash -d ls
  3. -r選項,表示清空所有命令的緩存,hash -r

(2)、編程語言

強類型變量編程語言

弱類型變量編程語言:
?

? (1)bash把所有變量統統視作字符型;
?

? 在指明做算數加減運算時自動轉換為數字類型
?

? 不支持浮點數據,除非借助於外在工具
?

? (2)bash中的變量無需事先聲明;相當於,把聲明和賦值過程同時實現;

? 變量聲明:類型,變量

(3)、變量

程序是由指令加數據組成,指令:由程序文件提供;數據(來源):常量,IO設備,文件,管道、變量等。

? 文件在被程序處理時,將文件加載到內存中進行修改,當文件要被修改多次的時候,存放文件的內存空間會依次序對文件進行處理,處理完成後存放到內存中的另一個位置
,文件第一階段處理完成後,第二階段和接下來的後續步驟要完成第一階段相同的步驟,文件加載到內存中暫存的是同一個內存空間,這個內存空間我們取名叫做變量,變量指向一個內存空間。

程序的另一種組成表示方法:程序是由算法加數據結構組成。

? 算法:設計解決問題的路徑
?

? 數據結構:數據以特定的結構組織起來

變量是由變量名加指向的內存空間組成。

變量賦值:shell中定義為name=value

變量類型

可以以數據的存儲格式、表示範圍、參與的運算三個方面進行分類。

(1)、以數據的存儲格式分

            字符型
            數值型
                  整型
                  浮點型
                      單精度浮點型
                      雙精度浮點型

            布爾型(true,false)

(2)、以作用範圍分,bash變量類型:

本地變量: 作用域為當前shell進程

環境變量: 作用域為當前shell進程及其子進程

局部變量: 作用域僅為shell進程中的某一個代碼片段(函數上下文)

位置參數變量: 向執行腳本的shell進程傳遞的參數;

特殊變量: shell內置的有特殊公用的變量;

                 例如一個特殊變量 $?:
                     $?:
                         0:成功
                         1-255:失敗

變量替換

把變量名出現的位置替換為其所指向的內存空間中的數據的過程;

變量替換的表示方式叫變量引用

bash變量引用:${var_name}或$var_name

變量名

變量名只能包含數字、字母和下劃線,而且不能以數字開頭:

變量名:見名知義,命名機制遵循某種法則;不能夠使用程序(編程語言)的保留字,例如if,else,then,while..

定義變量

(1)定義本地變量

本地變量:
                    本地變量賦值:  name=value
                    變量引用:  ${var_name},$var_name
                        "":變量名會替換為其直
                        ‘‘:變量名不會替換為其值
                    查看變量: set命令
                    撤銷變量:unset name(註意此處非變量引用,不能使用$符)

(2)定義環境變量

環境變量:
                     變量賦值:
                          (1) export name=value
                          (2) name=value
                              export name
                          (3) declare -x name=value 
                          (4) name=value
                              declare -x name 
                     變量引用:${name},$name

                     註意:bash內嵌了許多環境變量(通常為全大寫字符),用於定義bash的工作環境
PATH,HISTFILE,HISTSIZE,HISTFILESIZE,HISTCONTORL,SHELL,HOME,UID,PWD,OLDPWD

                     查看環境變量:export,declare -x,printenv,env
                     撤銷環境變量:unset name 

                       declare命令 shell內嵌命令
                          Set variable values and attributes.設置變量值和屬性。
                              -a    to make NAMEs indexed arrays (if supported)
                              -A    to make NAMEs associative arrays (if supported)
                              -i    to make NAMEs have the `integer‘ attribute
                              -l    to convert NAMEs to lower case on assignment
                              -r    to make NAMEs readonly
                              -t    to make NAMEs have the `trace‘ attribute
                              -u    to convert NAMEs to upper case on assignment
                              -x    to make NAMEs export

(3)只讀變量

只讀變量:
                   (1) declare -r name
                   (2) readonly name

                   只讀變量無法重新復制,並且不支持撤銷;存活時間為當前shell進程的生命周期,隨shell進程終止而終止;

(4)、邏輯運算

~]# COMMAND1; COMMAND2; COMMAND3; ...

我們用這樣的方式可以表示命令順序執行

(1)邏輯運算符

運算數: 真(true, yes, on, 1)
假(false, no, off, 0)

?

邏輯運算:

?

與:&& 
            1 && 1 = 1
            1 && 0 = 0
            0 && 1 = 0
            0 && 0 = 0
或:||
            1 || 1 = 1
            1 || 0 = 1
            0 || 1 = 1
            0 || 0 = 0

非:! 
             ! 1 = 0
             ! 0 = 1

         異或:運算數相同則為0,不同則為1

(2)短路法則

      ~]# COMMAND1 && COMMAND2
           COMMAND1為"假",則COMMAND2不會再執行;(為真表示命令執行成功,為假表示命令執行失敗)
           否則,COMMAND1為"真",則COMMAND2必須執行

      ~]# COMMAND1 || COMMAND2
           COMMAND1為"真",則COMMAND2不會再執行;
           否則,COMMAND1為"假",則COMMAND2必須執行

           示例:
              ~]# id $username || useradd $username

example.

            [[email protected] ~]# touch /tmp/test.etc1 && ls /etc > /tmp/test.etc1
            [[email protected] ~]# cat /tmp/test.etc1
            abrt
            adjtime
            aliases
            aliases.db
            alsa
            alternatives
            anacrontab
            asound.conf
            at.deny
            .
            .
            .

            [[email protected] ~]# touch123 /tmp/test.etc2 && ls /etc > /tmp/test.etc2
            bash: touch123: 未找到命令...
            [[email protected] ~]# cat /tmp/test.etc2
            cat: /tmp/test.etc2: 沒有那個文件或目錄            
            [[email protected] jacky]# id user1
            id: user1: no such user
            [[email protected] jacky]# id user1 || useradd user1
            id: user1: no such user
            [[email protected] jacky]# id user1
            uid=5014(user1) gid=5015(user1) 組=5015(user1)
            [[email protected] jacky]# id user1 || useradd user1
            uid=5014(user1) gid=5015(user1) 組=5015(user1)

(5)、shell腳本編程

1.編程語言的分類:

A、編程語言根據運行方式可以分為下列2種

? 1、編譯運行:源代碼需要由編譯器轉換為程序文件,而後才能運行,源代碼-->編輯器(編譯)-->程序文件
? C語言:

? 2、解釋運行:源代碼-->運行時啟動解釋器,由解釋器邊解釋邊運行;(源代碼本身不可運行,由解釋器將源代碼的數據處理運行)

B、根據其編程過程中功能的實現是調用庫還是調用外部的程序文件分類

? 1、腳本編程(此處為shell腳本編程):利用系統上的命令及編程組件進行編程;
?

? 2、完整編程:利用庫或編程組件進行編程;

C、據編程模型分類:

程序=指令+數據

1、過程式編程語言

過程式:以指令為中心來組織代碼,數據是服務於代碼;

             順序執行
             選擇執行
             循環執行
             代表:C,bash

2、 面向對象的編程語言

對象式:以數據位中心來組織代碼,圍繞數據來組織指令;

             類(class):同一類對象的抽象集合,可以實例化對象,
             方法(method):能夠對對象額外施加的操作:順序,選擇,循環
             對象
             代表:Java,C++,Python

2.shell腳本編程特性

1、shell腳本編程是過程式編程

2、解釋運行

3、依賴於外部程序文件

3.如何寫shell腳本

格式:

腳本文件的第一行,頂格:給出shebang,解釋器路徑,用以指明解釋執行當前腳本的解釋器程序文件

常見的解釋器:

#!/bin/bash

#!/usr/bin/python

#!/usr/bin/perl

文本編輯器:nano

在這裏我們可以用nano進行shell文件的創建和編輯。

 知識延伸:
 行編輯器:sed
 全屏幕編輯器:nano,vi,vim

shell腳本是什麽

簡單的來講,shell腳本就是命令的堆砌。但是,很多命令不具有冪等性,需要用程序邏輯來判斷運行條件是否滿足,以避免其運行中發生錯誤。

如何運行腳本

(1) 賦予執行權限,並直接運行此程序文件即可;

? chmod +x /PATH/TO/SCRIPT_FILE
?

? /PATH/TO/SCRIPT_FILE
?

(2) 直接運行解釋器,將腳本以命令行參數傳遞給解釋器程序;

bash /PATH/TO/SCRIPT_FILE
註意:
腳本中的空白行會被解釋器忽略;
腳本中,除了shebang,余下所有以#開頭的行,都被視作註釋行而被忽略;此即為註釋行;
shell腳本的運行是通過運行一個子shell進程實現的;
example:
        寫一個腳本,實現如下功能;
     (1)顯示/etc/目錄下所有以大寫P或小寫p開頭的文件或目錄本身; 
     (2)顯示/var目錄下的所有文件或目錄本身,並將顯示結果中的小寫字母轉換為大寫後顯示;
     (3)創建臨時文件/tmp/myfile.XXXX;  

        ~]# nano test_script.sh

?
?
? #!/bin/bash
?
? echo "Show some under /etc"
? ls -d /etc/[pP]*
?

        echo "Translate lower to upper"
        ls -d /var/* | tr ‘a-z‘ ‘A-Z‘

        echo "create temp file"
        mktemp /tmp/myfile.XXXX

4.bash的配置文件

bash配置文件分兩類

1、profile類:為交互式登錄的shell進程提供配置

2、bashrc類:為非交互式登錄的shell進程提供配置

登錄類型

1、交互式登錄shell進程:

? 直接通過某終端輸入賬號和密碼後登錄打開的shell進程
?

? 使用su命令:su - USERNAME,或者使用su -l USERNAME執行的登錄切換

2、非交互式登錄shell進程:

? su USERNAME執行的登錄切換;
?

? 圖形界面下打開的終端;
?

? 運行腳本時起的shell;

登錄shell進程之後查找應用配置文件的順序

交互式登錄shell進程:
           /etc/profil e--> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc--> /etc/bashrc

非交互式登錄shell進程:
           ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

profile類:

1、全局配置文件:對所有用戶都生效;
(註意:僅管理員可修改全局配置文件)

? /etc/profile
?

? /etc/profile.d/*.sh (開機運行腳本放到這裏方便管理,單獨定義環境變量也可以放在這裏例如定義JAVA_HOME環境變量)
?

2、用戶個人配置文件

? ~/.bash_profile

3、profile類配置文件的功用:

? A、用於定義環境變量;
?

? B、開機運行命令或腳本;

bashrc類:

1、 全局:

? /etc/bashrc

2、用戶個人:

? ~/.bashrc

3、功用:

? 1、定義本地變量;
?

? 2、定義命令別名;

生命周期

命令行中定義的特性,例如變量和別名作用域為當前shell進程的生命周期;

配置文件定義的特性,只對隨後新的shell進程有效;用以下方法讓通過配置文件定義的特性立即生效;

(1)通過命令行重復定義一次;
(2)讓shell進程重讀配置文件;
    ~]# source /PATH/FROM/CONF_FILE
(3)~]# . /PATH/FROM/CONF_FILE

二、文本處理工具grep

(1)、Linux文本處理三劍客

? grep,egrep,fgrep:文本過濾工具(模式:pattern)工具;

? grep:支持基本正則表達式,-E,-F

? egrep:擴展正則表達式,-G,-F

? fgrep:不支持正則表達式
?

? sed:stream editor,流編輯器;文本編輯工具;
?

? awk:Linux上的實現為gawk(GNU awk),文本報告生成器(格式化文本);

(2)、正則表達式

正則表達式:Regual Expression,REGEXP

由一類特殊字符及文本字符所編寫的模式,其中有些字符不表示其字面意義,而用於表示控制或通配的功能;

分為兩類:

? 基本正則表達式:BRE(basic regual expression)

? 擴展正則表達式:ERE(extended regual expression)

? 元字符:

? 舉例:\(hello[[:space:]]\+\)\+

(3)、grep

grep:Gloabal search REgulaer expression an Print out the line.全局搜索正則表達式並輸出相應行
       作用:文本搜索工具,genuine用戶指定的“模式(過濾條件)”對目標文本逐行進行匹配檢查;打印匹配到的行;

       模式:由正則表達式的元字符及文本字符所編寫出的過濾條件;(grep默認使用基本正則表達式,加選項-E使用擴展正則表達式)

       正則表達式引擎:

       grep [OPTIONS] PATTERN [FILE...]
       grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

            OPTIONS:
              --color=auto:對匹配到的文本著色後高亮顯示;
              -i: ignorecase,忽略字符的大小寫
              -o: 僅顯示匹配到的字符串本身;
              -v,--invert-match: 顯示不能被模式匹配到的行
              -E: 支持使用擴展的正則表達式元字符
              -q,--quiet,--slient:靜默模式,即不輸出任何信息;

              -A #:after,同時顯示匹配到的行的後#行
              -B #:before,前#行
              -C #:context,前後各#行

選項參考

    -a 不要忽略二進制數據。
    -A<顯示列數> 除了顯示符合範本樣式的那一行之外,並顯示該行之後的內容。
    -b 在顯示符合範本樣式的那一行之外,並顯示該行之前的內容。
    -c 計算符合範本樣式的列數。
    -C<顯示列數>或-<顯示列數>  除了顯示符合範本樣式的那一列之外,並顯示該列之前後的內容。
    -d<進行動作> 當指定要查找的是目錄而非文件時,必須使用這項參數,否則grep命令將回報信息並停止動作。
    -e<範本樣式> 指定字符串作為查找文件內容的範本樣式。
    -E 將範本樣式為延伸的普通表示法來使用,意味著使用能使用擴展正則表達式。
    -f<範本文件> 指定範本文件,其內容有一個或多個範本樣式,讓grep查找符合範本條件的文件內容,格式為每一列的範本樣式。
    -F 將範本樣式視為固定字符串的列表。
    -G 將範本樣式視為普通的表示法來使用。使用基本正則表達式
    -h 在顯示符合範本樣式的那一列之前,不標示該列所屬的文件名稱。
    -H 在顯示符合範本樣式的那一列之前,標示該列的文件名稱。
    -i 忽略字符大小寫的差別。
    -l 列出文件內容符合指定的範本樣式的文件名稱。
    -L 列出文件內容不符合指定的範本樣式的文件名稱。
    -n 在顯示符合範本樣式的那一列之前,標示出該列的編號。
    -q 不顯示任何信息。
    -R/-r 此參數的效果和指定“-d recurse”參數相同。
    -s 不顯示錯誤信息。
    -v 反轉查找。
    -w 只顯示全字符合的列。
    -x 只顯示全列符合的列。
    -y 此參數效果跟“-i”相同。
    -o 只輸出文件中匹配到的部分。

(4)、 基本正則表達式元字符

1.字符匹配

? .: 匹配任意單個字符;

  []:匹配指定範圍內的任意單個字符

? 有幾種特殊格式如下:

             [a-z]或[A-Z]:所有字母(範圍匹配時不區分字母大小寫)
             [0-9]:    0-9所有數字
             [a-z0-9]:a到z,0到9(所有數字和字母)
             [abcxyz]: a,b,c,x,y,z中的任意單個字符,區分大小寫
             [[:upper:]]: 所有大寫字母
             [[:lower:]]: 所有小寫字母
             [[:alpha:]]: 所有字母
             [[:digit:]]: 所有數字
             [[:alnum:]]: 所有的字母和數字
             [[:space:]]: 所有空白字符
             [[:punct:]]: 所有標點符號

? [^]:匹配指定範圍外的任意單個字符

             [^[:upper:]]   匹配非大寫字母以外的任意單個字符
             [^0-9]         匹配數字以外的任意單個字符(非數字字符)
             [^[:alnum:]]   匹配字母和數字以外的任意單個字符(例如空白符合標點)

2.匹配次數

用在要指定其出現的次數的字符的後面,用於限制其前面字符出現的次數;默認工作於貪婪模式(能匹配多少個字符就會匹配多少);

     *:匹配其前面的字符任意此;0,1,多次;
                    例如:grep "x*y"
                        abxy
                        aby
                        xxxxxy
                        yab
     .*: 匹配任意長度的任意字符
     \?: 匹配其前面的字符0次或1次;即其前面的字符可有可無;
     \+: 匹配其前面的字符1次或多次;即其前面的字符要出現至少1次;
     \{m\}: 匹配其前面的字符m次;
     \{m,n\}: 匹配其前面的字符至少m次,至多n次;
     \{0,n\}:至多n次
     \{m,\}:至少m次

example.

[[email protected] ~]# nano grep.txt
[[email protected] ~]# grep "x*y" grep.txt 
                           abxy
                            aby
                            xxxxxy
                            yab
[[email protected] ~]# grep "x\?y" grep.txt 
                           abxy
                            aby
                            xxxxxy
                            yab
[[email protected] ~]# grep "x\+y" grep.txt 
                           abxy
                            xxxxxy
[[email protected] ~]# grep "x\1y" grep.txt 
grep: 無效的向後引用
[[email protected] ~]# grep "x\{1}y" grep.txt 
grep: 不匹配的 \{
[[email protected] ~]# grep "x\{1\}y" grep.txt 
                           abxy
                            xxxxxy
[[email protected] ~]# grep "x\{2\}y" grep.txt 
                            xxxxxy
[[email protected] ~]# grep "x\{2,5\}y" grep.txt 
                            xxxxxy
[[email protected] ~]# grep "x\{1,5\}y" grep.txt 
                           abxy
                            xxxxxy

3.位置錨定

^: 行首錨定; 用於模式的最左側

$: 行尾錨定; 用於模式的最右側

^PATTERN$: 用於 PATTERN來匹配整行;

? ^$: 空白行;

? ^[[:space:]]*: 空行或包含空白字符的行;

    example.
                            [[email protected] ~]# grep root /etc/passwd
                            root:x:0:0:root:/root:/bin/bash
                            operator:x:11:0:operator:/root:/sbin/nologin
                            rootkit:x:5016:5017::/home/rootkit:/bin/bash
                            user7:x:5017:5018::/home/user7:/bin/chroot
                            chrooter:x:5018:5019::/home/chrooter:/bin/bash
                            [[email protected] ~]# grep "^root" /etc/passwd
                            root:x:0:0:root:/root:/bin/bash
                            rootkit:x:5016:5017::/home/rootkit:/bin/bash
                            [[email protected] ~]# grep "root$" /etc/passwd
                            user7:x:5017:5018::/home/user7:/bin/chroot

單詞: 非特殊字符組成的連續字符(字符串)都稱為單詞;

\<或\b: 詞首錨定,用於單詞模式的左側;
\>或\b: 詞尾錨定,用於單詞模式的右側;
\<PATTERN\>:匹配完整單詞;
    example.
                    [[email protected] ~]# grep "\<root" /etc/passwd
                    root:x:0:0:root:/root:/bin/bash
                    operator:x:11:0:operator:/root:/sbin/nologin
                    rootkit:x:5016:5017::/home/rootkit:/bin/bash
                    [[email protected] ~]# grep "\broot" /etc/passwd
                    root:x:0:0:root:/root:/bin/bash
                    operator:x:11:0:operator:/root:/sbin/nologin
                    rootkit:x:5016:5017::/home/rootkit:/bin/bash
                    [[email protected] ~]# grep "root\>" /etc/passwd
                    root:x:0:0:root:/root:/bin/bash
                    operator:x:11:0:operator:/root:/sbin/nologin
                    user7:x:5017:5018::/home/user7:/bin/chroot                        
                    [[email protected] ~]# grep "\<root\>" /etc/passwd
                    root:x:0:0:root:/root:/bin/bash
                    operator:x:11:0:operator:/root:/sbin/nologin

4.分組及引用

\(\): 將一個或多個字符捆綁在一起,當作一個整體進行處理;
      例如:
            \(xy\)*ab

Note: 分組括號中的模式匹配到的內容會被正則表達式引擎自動記錄與內部的變量中,這些變量為:
\1: 模式從左側起,第一個左括號以及與之匹配的右括號之間的模式所匹配到的字符;
\2: 模式從左側起,第二個左括號以及與之匹配的右括號之間的模式所匹配到的字符;
\3:
...

後向引用: 引用前面的分組括號中的模式所匹配到的字符;

        example.
                He likes his lover.
                He loves his lover.
                She likes her liker.
                She love her liker.

            [[email protected] tmp]# grep "\(l..e\).*\1" loves.txt
            He loves his lover.
            She likes her liker.

(5)、egrep

egrep支持擴展的正則表達式實現類似於grep文本過濾功能;grep -E 實現同樣的功能.

     命令:egrep [OPTIONS] PATTERN [FILE...]

          OPTIONS:
              --color=auto:對匹配到的文本著色後高亮顯示;
              -i: ignorecase,忽略字符的大小寫
              -o: 僅顯示匹配到的字符串本身;
              -v,--invert-match: 顯示不能被模式匹配到的行
              -E: 支持使用擴展的正則表達式元字符
              -q,--quiet,--slient:靜默模式,即不輸出任何信息;

              -A #:after,同時顯示匹配到的行的後#行
              -B #:before,前#行
              -C #:context,前後各#行
          擴展正則表達式的元字符:
            字符匹配
                  .:任意單個字符
                 []:指定範圍內的任意單個字符
                 [^]指定範圍外的任意單個字符

            次數匹配
                 *:任意次,0,1或多次;
                 ?:0次或1次,其前的字符是可以可惡的;
                 +:其前字符至少1次;
                 {m}:其前的字符m次;
                 {m,n}:至少每次,至多n次;
                     {0,n}
                     {m,}

            位置錨定
                ^: 行首錨定;
                $: 行尾錨定;
                \<,\b: 詞首錨定;
                \>,\b: 詞尾錨定;

            分組及引用;
                (): 分組; 括號內的模式匹配到的字符會被記錄與正則表達式引擎的內部變量中;
                向後引用: \1,\2,...         (只能在正則表示中引用)

            或:
                 a|b: a或者b;
                 C|cat: C或cat
                 (C|c)at: cat或Cat

(6)、fgrep

? fgrep: 不支持正則表達式元字符;

? 當無需要用到元字符去編寫模式時,使用fgrep性能更好;

三、其他文本查看及處理工具

(1)、wc

wc: word count 單詞統計, print newline, word, and byte counts for each file

命令:wc [OPTION]... [FILE]...
       -l: lines,行數
       -w: words,單詞數
       -c: bytes,字節數
    example.
                [[email protected] ~]# wc /etc/fstab 
                 12  60 541 /etc/fstab
                [[email protected] ~]# wc -l /etc/fstab 
                12 /etc/fstab
                [[email protected] ~]# wc -w /etc/fstab 
                60 /etc/fstab
                [[email protected] ~]# wc -c /etc/fstab 
                541 /etc/fstab

(2)、CUT

cut:文本截取工具

? cut - remove sections from each line of files

命令:cut OPTION... [FILE]...
         OPTION:
            -d CHAR: 以指定的字符為分隔符;-d後面可以不跟空格(-d‘‘ 表示以空格為分隔符)
            -f FIELDS: 挑選出的字段;
                #: 指定的單個字段;
                #-#: 連續的多個字段;
                #,#: 離散的多個字段;
   example. 
         ~]# cut -d: -f1,3-5,7 /etc/passwd

(3)、sort

sort:排序命令

sort - sort lines of text files
     命令: sort [OPTION]... [FILE]...
                -n:基於數值大小進行排序,而非字符
                -t CHAR: 指定字段分隔符;
                -k #: 用於排序比較的字段
                -r: 逆序排序;
                -f: 忽略字符大小寫
                -u, --unique: 重復的行只保留一份; 
                        重復:連續且相同
example.
           A:
            sort -t: -k3 -n /etc/passwd      //將用戶信息以UID的數值大小排序
           B:
            [[email protected] ~]# cut -d: -f7 /etc/passwd | sort -u
            /bin/bash
            /bin/chroot
            /bin/csh
            /bin/sync
            /bin/tcsh
            /bin/zsh
            /sbin/halt
            /sbin/nologin
            /sbin/shutdown
            [[email protected] ~]# cut -d: -f7 /etc/passwd | sort -u | wc -l         
            9
                //表示當前系統的用戶有幾種在使用的shell(Linux哲學思想之一組合簡單命令完成復雜任務)

(4)、uniq

uniq:報告或移除重復的行

命令: uniq [OPTION]... [INPUT [OUTPUT]]
                -c, 顯示每一行重復出現的次數
                -u, 僅顯示未曾重復過的行
                -d, 僅顯示存在重復的行
example.
            [[email protected] ~]# cut -d: -f7 /etc/passwd | sort | uniq
            /bin/bash
            /bin/chroot
            /bin/csh
            /bin/sync
            /bin/tcsh
            /bin/zsh
            /sbin/halt
            /sbin/nologin
            /sbin/shutdown
            [[email protected] ~]# cut -d: -f7 /etc/passwd | sort | uniq -u
            /bin/chroot
            /bin/csh
            /bin/sync
            /bin/tcsh
            /bin/zsh
            /sbin/halt
            /sbin/shutdown
            [[email protected] ~]# cut -d: -f7 /etc/passwd | sort | uniq -c
                 21 /bin/bash
                  1 /bin/chroot
                  1 /bin/csh
                  1 /bin/sync
                  1 /bin/tcsh
                  1 /bin/zsh
                  1 /sbin/halt
                 41 /sbin/nologin
                  1 /sbin/shutdown
            [[email protected] ~]# cut -d: -f7 /etc/passwd | sort | uniq -d
            /bin/bash
            /sbin/nologin

(5)、diff

diff - compare files line by line,逐行比較文件的不同之處

命令: diff [OPTION]... FILES

      diff /PATH/TO/OLDFILE /PATH/TO/NEWFIEL > /PATH/TO/PATCH_FILE
           -U: 使用unified機制,即顯示要修改的行的上下文,默認為3行
 patch:向文件打補丁
      patch [OPTIONS] -i /PATH/TO/PATCH_FILE /PATH/TO/OLDFILE

      patch /PATH/TO/OLDFILE < /PATH/TO/PATCH_FILE             以輸入重定向實現

PS:diff可以將2個文件夾下的文件逐一比較,可以以逐一生成補丁文件,逐一打補丁,變得和新文件一模一樣
example.

            [[email protected] tmp]# diff fstab fstab.new 
            2c2                                             //原文件的第二行change為新文件的第二行
            < #                                             //原文件#刪除
            ---                                             //分割線
            > ##                                            //新文件的第二行為## 
            8c8                                             //原文件的第8行change為新文件的第8行
            < #                                             //原文件#刪除
            ---                                             //分割線
            > #jacky                                        //線文件的第8為#jacky
            [[email protected] tmp]# diff fstab fstab.new > fstab.patch          //比較新舊文件,重定向到文件fstab.patch,達成生成補丁的目的
            [[email protected] tmp]# cat fstab.patch                       //查看補丁文件
            2c2
            < #
            ---
            > ##
            8c8
            < #
            ---
            > #jacky
            [[email protected] tmp]# patch -i fstab.patch fstab        //給fstab文件打補丁
            patching file fstab
            [[email protected] tmp]# diff fstab fstab.new             //再次比較,因為fstab文件打了補丁和fstab.new文件內容一樣了,比較沒有不同,不會有結果輸出
            [[email protected] tmp]# 
            [[email protected] tmp]# patch -R -i fstab.patch fstab     //逆向補丁(取消補丁的效果)
            patching file fstab
            [[email protected] tmp]# diff -u fstab fstab.new          //加-u選項統一上下文的輸出行數(默認為3行),這是另一種風格的比較結果輸出方式
            --- fstab   2019-05-08 22:03:29.007621543 +0800
            +++ fstab.new   2019-05-08 21:30:43.782458462 +0800
            @@ -1,11 +1,11 @@

            -#
            +##
             # /etc/fstab
             # Created by anaconda on Tue Mar 19 19:01:41 2019
             #
             # Accessible filesystems, by reference, are maintained under ‘/dev/disk‘
             # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
            -#
            +#jacky
             /dev/mapper/centos-root /                       xfs     defaults        0 0
             UUID=ded54529-49da-4e0f-b847-efeb43908dad /boot                   xfs     defaults        0 0
             /dev/mapper/centos-home /home                   xfs     defaults        0 0

shell腳本基礎和grep使用