從shell眼中看世界–展開和引用

這篇博客的目的在于加深對于展開和引用的理解,闡釋展開和引用之間聯系。

‘ ‘ :強引用,其中的變量引用不會被替換為變量值,而保持原字符串
       ” “:弱引用,其中的變量引用會被替換為變量值
    如果之前對于’ ‘和” “的理解只停留在上述兩句話的這個階段,那么讀完這篇博客相信你一定會有所收獲。(本文會告訴你什么叫做一萬句頂一句。)

    展開
        0.展開機制說明                  
        1.路徑名展開                 *
        2.波浪線展開                 ~
        3.算術表達式展開           $(()) $[]
        4.花括號展開                 {}
        5.參數展開                    $
        6.命令替換                    $()   ` `

    0.展開機制說明
        echo是一個shell內部命令,作用是在標準輸出中打印出它的文本參數。這里會使用echo命令來對所有展開進行說明,所以這一部分會非常容易理解。

        # echo this is a test
        this is a test


        echo將文本參數直接打印出來。

        # echo *
        aa addr.data anaconda-ks.cfg bin Checkos.sh hostch.sh hosts.bak hosts.BAK input ls-output.txt ls.txt Pics ping1.sh poem.txt shoplist.data test1.sh testuser.sh testz.sh tongku.sh


        如何工作:
        這里echo并沒有直接打印,而是列出了當前工作目錄下的所有文件(除了隱藏文件)及目錄。這說明在echo命令執行前,shell把展開成了另外的東西。在對于通配符的學習中可以知道匹配任意長度的任意字符。當回車鍵被按下時,shell在命令被執行前自動展開當前工作目錄下任何符合條件的文件名,所以echo命令所接收到的不是,而是*所展開成的結果。這就解釋了echo * 執行結果。

        
    1.路徑名展開
        在展開機制說明中提到的展開就是一種路徑名展開。
        舉例說明

        [root@localhost ~]# ls
        aa               Checkos.sh  input          ping1.sh       testuser.sh
        addr.data        hostch.sh   ls-output.txt  poem.txt       testz.sh
        anaconda-ks.cfg  hosts.bak   ls.txt         shoplist.data  tongku.sh
        bin              hosts.BAK   Pics           test1.sh

        /root目錄中內容
        

        [root@localhost ~]# echo h*
        hostch.sh hosts.bak hosts.BAK


        h*展開為目錄下以h開頭的文件名
       

        [root@localhost ~]# echo *h
        Checkos.sh hostch.sh ping1.sh test1.sh testuser.sh testz.sh tongku.sh


        *h展開為目錄下以h結尾的文件名

        [root@localhost ~]# echo [[:upper:]]*
        Checkos.sh Pics


        [[:upper:]]*展開為目錄下以大寫字母開頭的文件名

        所謂展開就是shell對于命令行參數進行解釋,改變其字面意義上的內容。(理解展開的關鍵)
        路徑名展開把參數展開為符合匹配模式的內容。

    2.波浪線展開
        波浪線~是有特殊含義的。shell會對其進行特定解釋。
        兩種用法:
        ~后跟用戶名,展開為指定用戶的家目錄。
        ~,不指定用戶名,展開為當前用戶的家目錄。

        [root@localhost ~]# echo ~
        /root
        [root@localhost ~]# echo ~cold
        /home/cold


        
        波浪線展開:shell對~作特殊的解釋說明。

    3.算術表達式展開
        shell允許算術表達式通過展開來執行。其格式$((expression))或者$[expression]
        操作符:+、-、*、/、%、**
        注意事項:
        算術表達式中空格并不重要,并且表達式可以嵌套。
        一對括號可以把子表達式括起來。由此可以簡化嵌套。
        舉例說明

        [root@localhost ~]# echo $((2+2))
        4
        [root@localhost ~]# echo $[2+2]
        4
        [root@localhost ~]# echo $(($((5**2))*3))
        75
        [root@localhost ~]# echo $(((5**2)*3))
        75


        算術表達式展開:執行算術表達式,并用結果替換之

    4.花括號展開
        相當有趣的一種展開。我將其理解為每個選項都選擇一次。
        通過實例更容易說明其作用。

        [root@localhost ~]# echo Front-{A,B,C}-Back
        Front-A-Back Front-B-Back Front-C-Back


        選項用“,”隔開,ABC三個選項

        [root@localhost ~]# echo Number_{1..5}
        Number_1 Number_2 Number_3 Number_4 Number_5


        一系列整數

        [root@localhost ~]# echo {Z..A}
        Z Y X W V U T S R Q P O N M L K J I H G F E D C B A


        一系列倒序大寫字母

        [root@localhost ~]# echo a{A{1,2},B{3,4}}b
        aA1b aA2b aB3b aB4b


        嵌套模式

        注意事項:
        {}中不能嵌入空白字符。下面是C前加入一個空白符后的執行結果。

        [root@localhost ~]# echo Front-{A,B, C}-Back
        Front-{A,B, C}-Back


        {}可以嵌套。

        這種展開最普遍的應用是,創建一系列的文件或目錄列表。

        [root@localhost Pics]# mkdir {2015..2017}0{1..9} {2015..2017}{10..12}
        [root@localhost Pics]# ls
        201501  201505  201509  201601  201605  201609  201701  201705  201709
        201502  201506  201510  201602  201606  201610  201702  201706  201710
        201503  201507  201511  201603  201607  201611  201703  201707  201711
        201504  201508  201512  201604  201608  201612  201704  201708  201712


        看,相當的快捷方便。

    5.參數展開
        $變量名 將變量替換為變量值

        [root@localhost Pics]# echo $USER
        root


        USER系統定義的變量,變量值為當前用戶名

        [root@localhost Pics]# x=10
        [root@localhost Pics]# echo $x
        10


        給x賦值為10,$x會被shell自動替換為10

    6.命令替換
        命令替換允許我們把一個命令的輸出作為一個展開模式來使用。
        格式:$(command)   `command`

        [root@localhost ~]# which man
        /usr/bin/man
        [root@localhost ~]# ls -l `which man`
        -rwxr-xr-x. 1 root root 102736 Jun 10  2014 /usr/bin/man
        [root@localhost ~]# ls -l $(which man)
        -rwxr-xr-x. 1 root root 102736 Jun 10  2014 /usr/bin/man


        注意:命令的輸出會被直接當成參數。如果命令輸出不能直接作為下一條命令的參數,將不能正常執行。
        例如

        [root@localhost ~]# which cp
        alias cp='cp -i'
            /usr/bin/cp
        [root@localhost ~]# ls -l `which cp`
        ls: invalid option -- '''
        Try 'ls --help' for more information.


        which cp輸出除文件路徑還有其他內容,ls命令報錯。

    引用
    shell有許多方式可以完成展開,現在是時候學習怎么來控制展開了。

    [root@localhost ~]# echo this is a    test
    this is a test


    shell從echo命令的參數列表中刪除多余的空格。

    [root@localhost ~]# echo The total is $100.00
    The total is 00.00


    參數展開把$1 的值替換為一個空字符串,因為1是沒有定義的變量。
    這里shell自作主張的對輸入的字符串進行轉換,有時這并不是我們所期望的。
    shell提供了引用機制,來有選擇地禁止不需要的展開。
    

    1.雙引號
        文本放在放在雙引號之中,shell使用的特殊字符除$、\、`之外都會失去它們的特殊含義,被當做特殊字符對待。
        回想上面講到的關于展開的內容,~波浪線展開,{}花括號展開,*等通配符的路徑名展開,單詞分割都被禁止。算術表達式展開,參數展開和命令替換仍然有效。
        
        注:什么是單詞分割
        在默認情況下單詞分割會在單詞中尋找空格、制表符和換行符,并把它們看作單詞之間的界定符。它們只作為分隔符使用。
        舉例說明

        [root@localhost ~]# echo this is a    test
        this is a test


        這里多個空格只是作為分隔符使用,在上面這個例子中shell認為給出了四個參數,分別是this、is、a、test,將這四個參數傳遞給echo命令,因此執行結果中看不到多出的空格符的影響。
        [root@localhost ~]# echo “this is a    test”
        this is a    test
        在這個例子中this is a    test 文本被包含在””中,單詞分割被禁止,內嵌的空格不再被當做界定符,而被作為參數的一部分。因此運行結果中輸入的空格被保留了下來。

        這里還有一個關于單詞分割的有趣例子,給出運行結果。

        [root@localhost ~]# echo $(cal)
        April 2017 Su Mo Tu We Th Fr Sa 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 ~]# echo "$(cal)"
             April 2017     
        Su Mo Tu We Th Fr Sa
                           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


    2.單引號
        單引號禁止包含文本的所有展開。
        舉例說明

        [root@localhost ~]# echo text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER
        text /root/ls-output.txt /root/ls.txt /root/poem.txt a b cold 4 root


        所有展開都被允許。

        [root@localhost ~]# echo "text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER"
        text ~/*.txt {a,b} cold 4 root


        只有命令替換,算術表達式展開,參數展開被允許。

        [root@localhost ~]# echo 'text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER'
        text ~/*.txt {a,b} $(echo cold) $((2+2)) $USER


        所有展開都被禁止。

    3.轉義字符
        在雙引號中使用轉義字符,可以有選擇地阻止展開。
 

        [root@localhost ~]# echo "The balance for $USER is:$5.00"
        The balance for root is:.00   


        兩個$都被當做參數展開。

        [root@localhost ~]# echo "The balance for $USER is:\$5.00"
        The balance for root is:$5.00


        阻止了$5.00的展開,\$被顯示為$。

        在雙引號中反斜杠失去它的特殊含義,被當做普通字符。
        

    總結
    《The Linux Command Line》中是這樣說明這一章節的:
     隨著我們繼續學習 shell,你會發現使用展開和引用的頻率逐漸多起來,所以能夠很好的理解他們的工作方式很有意義。事實上,可以這樣說,他們是學習 shell 的最重要的主題。 如果沒有準確地理解展開模 式,shell 總是神秘和混亂的源泉,并且 shell 潛在的能力也 浪費掉了。

原創文章,作者:maru,如若轉載,請注明出處:http://www.www58058.com/73499

(0)
marumaru
上一篇 2017-04-16 22:13
下一篇 2017-04-16 22:23

相關推薦

  • N25-第三周博客作業

    1、列出當前系統上所有已經登錄的用戶的用戶名,注意:同一個用戶登錄多次,則只顯示一次即可。 [root@node1 ~]# who | cut -d" " -f1 | uniq (unknown) root 2、取出最后登錄到當前系統的用戶的相關信息…

    Linux干貨 2016-12-17
  • 優云Automation:實現IT服務彈性伸縮的利器

    隨著互聯網業務快速持續增長,IT資源使用量按需變化成為常態,這就要求信息部門能快速響應資源使用的變化要求,對運維提出不小挑戰。比如電商、在線教育等企業經常推出一些秒殺、搶紅包活動,在特定時間段對資源的利用處于高峰期,之后基本處于空閑。 幾年前,我們從申請采購到應用部署上線都只能人工操作,需要提前幾個月開始規劃。如今通過云平臺能很好實現資源按需動態管理,運維人…

    系統運維 2017-03-15
  • ELK 日志分析實例

    網海過客www.chinasa.net ELK 日志分析實例一、ELK-web日志分析二、ELK-MySQL 慢查詢日志分析三、ELK-SSH登陸日志分析四、ELK-vsftpd 日志分析 一、ELK-web日志分析 通過logstash grok正則將web日志過濾出來,輸出到Elasticsearch 搜索引擎里,通過Kibana前端展示。  …

    Linux干貨 2016-06-03
  • 圖解LVM(邏輯卷管理)

    圖解LVM 1 什么是LVM?為什么要使用LVM? lvm(Logical Volume Manager)邏輯卷管理,是一種更為靈活彈性的磁盤管理工具。 通過邏輯卷管理,能夠解決傳統磁盤管理管理困難的問題,比如靈活的增刪磁盤容量,增刪磁盤分區等。 LVM由pv(Physical Volume),vg(Volume Group),lv(logical volu…

    2017-04-23
  • Linux的主要發行版及區別

    Linux的主要發行版介紹 主流的發行版 Linux至上世紀90年代基于Unix而誕生,至今其發行版有幾百種之多,但其主流的發行版有三個系列。 Debian系 Ubuntu屬于Debinan系。 Redhat系CentOS屬于Redhat系。Slackware系SUSE Linux即屬于Slackware系。 主要區別 軟件包管…

    Linux干貨 2016-10-29
  • RAID與邏輯卷

        RAID與邏輯卷作為磁盤管理的方式,各有各的優勢。RAID是多個磁盤合成一個陣列,以便提供更好的性能;邏輯卷相對于分區來說,可以在線擴展空間,也可以縮減空間??梢岳密浖姆绞絹韺崿FRAID與邏輯卷。 一、利用軟件方式實現RAID     利用sdb sdc sdd sd…

    2017-08-12

評論列表(1條)

  • renjin
    renjin 2017-04-21 09:40

    很明顯,比上次寫的博客都有一個大的提升,主要介紹了符號展開在linux shell中的用法,內容寫的很詳細,也很生動,排版還需要一個提升的過程,加油,加油

欧美性久久久久