從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
下一篇 2017-04-16

相關推薦

  • CentOS6下的網絡信息配置

    簡介     我們都知道在我們互聯網中,所有的通信都通過網絡來完成的,有了網絡當然也要有對應的地址,MAC地址是固定不變的,所以能變的只有IP的地址,那么今天來帶給大家如何在CentOS6中如何配置網卡。當然一下的所有命令都是在CentOS6中進行的。 一、網卡的配置文件    1.操作網卡的命令 …

    Linux干貨 2017-03-20
  • linux中特殊符號用法

    1 #    #  管理員賬戶    $  普通賬戶   在腳本中 #也常出現在一行的開頭,或者位于完整指令之后,這類情況表示符號后邊是注解文字,不會被執行 例如     #!/bin/bash     #th…

    Linux干貨 2016-08-15
  • 馬哥教育網絡班22期+第四周課程練習

    1、復制/etc/skel目錄為/home/tuser1,要求/home/tuser1及其內部文件的屬組和其它用戶均沒有任何訪問權限 [root@localhost ~]# cp -rf /etc/skel/ /home/tuser1 &> /dev/null [root@localhost ~]# chmod -R go= /home/tus…

    Linux干貨 2016-09-07
  • linux基礎之bash特性知識點

    1、 Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示。     Linux 一切皆文件。個人理解 在linux下的命令操作都算是對文件操作     那么文件管理命令類命令可以分為下面幾類     目錄操作: &nbs…

    Linux干貨 2016-09-24
  • 馬哥教育網絡班21期+第2周課程練習

    一、Linux文件管理類命令匯總 1、文件的復制命令:cp 復制命令:cp     cp [OPTION]… [-T] SOURCE DEST     cp [OPTION]… SOURCE… DI…

    Linux干貨 2016-07-29
  • 馬哥教育網絡21期+第一周練習博客

    一、描述計算機的組成及其功能。   計算機設備是由運算器、控制器、存儲器、輸入設備和輸出設備組成。它們的功能和對應設備分別如下: 運算器(arithmetic unit):在計算機中執行各種算術和邏輯運算操作的部件。運算器包括寄存器、執行部件和控制電路3個部      &nbsp…

    Linux干貨 2016-07-12

評論列表(1條)

  • renjin
    renjin 2017-04-21 09:40

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

欧美性久久久久