bash shell 臨時筆記

 

1. 1變量替換

1. 2參數替換

 

1.1.1 變量的名字是它的值保存的地方。引用它的值稱爲變量替換(variable substitution)。.

              如 果variable1是一個變量的名字,那麼$variable1就是引用這個變量的值

              變量賦值: var_name="var_value"     等號兩邊不能有空格 ;給變量賦的值中有空白字符,“ ”引號是必須的

                                read var_name

                                for  var_name in num1 num 2

                                var_name=$(cmd)   命令替換,注意要保持命令行輸出的完整性,最好var_name="$(cmd)" ,使用雙引號

             變量替換: $var_name 等同於 ${var_name}   在某些場合使用$variable形式會引起錯誤,這時你可能需要使用${variable}的形式了

                                "$var_name"       在一個雙引號(" ")裏的變量引用不會禁止變量替換。所以雙引號被稱爲部分引用,有時也稱爲"弱引用"

                               變量替換不能用‘$var_name’     一個單引號裏(' ')的變量替換是被禁止的,變量名只被解釋爲普通的字面意思

 

1.1.2  一個未初始化的變量有一個”null”值――表示從沒有被賦值過(注意null值不等於零)。雖然有時在數學運算會被當成0 ,但是不可靠,但是該行爲無法預期 。

1.1.3 變量沒有類型。

         本質上來說,Bash變量是字符串,但是根據環境的不同,Bash允許變量有整數計算和比較。其中的決定因素是變量的值是不是隻含有數字

1.1.4特殊變量種類

        局部變量     local loc_var=23       # 聲明爲局部變量

        環境變量

             1.1.4.1

               每次一個Shell啓動時,它都會創建新的合適的環境變量。如果它增加或是更新一個環境變量,都會使這個Shell的環境表得到更新(譯者注:換句話說,更改或增加

               的變量會立即生效),並且這個Shell所有的子進程(即它執行的命令)能繼承它的環境變量。(譯者注:準確地說,應該是後繼生成的子進程纔會繼承Shell的新環

               境量,已經運行的子進程並不會得到它的新環境變量)。

             1.1.4.2

              如果一個腳本要設置一個環境變量,則需要將它導出(”export”),也就是說要通知到腳本的環境表。這就是export命令的功能。這樣子腳本纔會看到這個新修改變量

              一個腳本只能導出(export)變量到子進程,也就是說只能導出到由此腳本生成的命令或進程中。在一個命令行中運行的腳本不能導出一個變量影響到命令行的環境

              子進程不能導出變量到生成它的父進程中

       位置參數

               注意$0

                     shift  ;

                     $* $@ ; $* 和$@ 結合不同的IFS,代表的東西可能不一樣

2.1.1設置變量的屬性 r x i

           declaretypeset內建命令(它們是完全相同的)可以用來限定變量的屬性.

           declare [+/-][rxi][變量名稱=設置值] declare-f

          參數說明

                +/-  "-"可用來指定變量的屬性,"+"則是取消變量所設的屬性

                -f  僅顯示函數

                 r  將變量設置爲只讀。

                 x  指定的變量會成爲環境變量,可供shell以外的程序來使用。

                 i  [設置值]可以是數值,字符串或運算式。

                 使用內建的declare可以來限定變量的範圍, foo (){    declare FOO="bar"    }   局部變量

2.1.2 變量的間接引用

         變量間接引用的實際用處是什麼? 它提供了Bash具有C中一點指針的功能 .

         Bash不支持指針運算,這極大地限制了間接引用的用處。事實上,在腳本語言裏間接引用是一個蹩腳地東西

        a=letter_of_alphabet   # 變量"a"保存着另外一個變量的名字.    letter_of_alphabet=z

         # 間接引用.   eval a=\$$a

2.1.3 間接引用用到的命令字 eval

        eval的作用是再次執行命令行處理,也就是說,對一個命令行,執行兩次命令行處理

        2.1.3.1與eval一起記憶的一個命令let

             let 命令是 BASH 中用於計算的工具,用於執行一個或多個表達式,變量計算中不需要加上 $ 來表示變量。如果表達式中包含了空格或其他特殊字符,則必須引起來。

             shell程序中的操作默認都是字符串操作,在要運行數學運算符的時候可能得到意想不到的答案,所以用let

        2.1.3.2 與let一起的算術運算

               let不允許只出現等號右邊的計算,用“ ”或者表達式中間沒有空格,不需要$ let ″j=i*6+2″等價於((j=i*6+2)),

               var=`expr$var+1`   將需要運算的表達式寫入在expr 後面,參數與運算符號中間有空格隔開 

              (())、expr 可以只有等號右邊的計算,由$((...))、$(expr ...)、`expr ...` 查看返回結果                      expr表達式參數間必須有空格

     let和(())運行是內建命令,使用相同的算法。       let或者表達式用“”,或者表達式中間沒有空格
              let 和 expr 的運算是整數運算,不包括浮點預算

2.1.4 變量的檢查和初始化賦值

         ${parameter-default}, ${parameter:-default}

                   前者變量沒有被聲明(變量的值是NULL,也看做被聲明),就使用這個default作爲默認值;

                   後者變量沒有被設置(變量的值是NULL,也是沒有被設置),就使用default默認值

         ${parameter=default}, ${parameter:=default}  等同於上面

    ${parameter?err_msg}, ${parameter:?err_msg} 變量沒有被聲明或者被設置,打印err信息

    ${parameter+alt_value},${parameter:+alt_value}

   如果變量parameter被聲明或被設置,使用alt_value作爲新值,否則使用空字符串

 

2.1.5 對變量的值就行修改

 注意: Pattern 可以使用正則表達式,但是Replacement不能使用正則表達式

    ${var#Pattern}, ${var##Pattern}

“刪除”從$var前端 開始的最短 或 最長匹配$Pattern的字符串.  必須是從頭第一個字母開始的匹配,否則替換不了

    ${var%Pattern}, ${var%%Pattern}

”刪除“從$var後端 開始的最短 或 最長匹配$Pattern的字符串。 必須是結尾最後一個字母的匹配。       記憶方法:鍵盤上三個鍵的位置緊挨着:#$%

    ${var/#Pattern/Replacement}

”替換“如果變量var前綴匹配模式Pattern,則用Replacement代替匹配模式的字符串.

    ${var/%Pattern/Replacement}

”替換“如果變量var後綴匹配模式Pattern,則用Replacement代替匹配模式的字符串.

 

        注意: 這些pos 不能使用正則表達式------------------------------------

    ${var:pos} ${var:(-pos)} 

變量var被展開成從位移pos個字符往後的值.pos爲負值,則從字符後面的倒數pos位置提取字符

    ${var:pos:len}

從變量var中展開成從位移pos的字符往後最長爲len的字符串。

    ${var/Pattern/Replacement}

在變量var第一個匹配Pattern的字符串用Replacement代替.     變量中間的字符,不一定是開頭或者結尾的字符

如果省略了Replacement ,則第一個匹配Pattern的字符串會被刪除.

    ${var//Pattern/Replacement}

全局替換Global replacement.所有在變量var中被Pattern匹配到的都由Replacement代替.

 2.1.6 查看定義的變量        ${!varprefix*}, ${!varprefix@}

匹配所有前面聲明過的變量,並且變量名以varprefix開頭.

    ${!name[@]}  ${!name[*]}
      如果name爲一個數組變量,那麼結果是該數組的所有下標的列表。如果name不是數組,那麼,如果name爲空,結果就爲空,如果name不爲空,結果就爲0.2.1.7 變量的長度    ${#var}

字符串長度(即變量$var的字符個數)。

對於數組來說,${#array}是數組的第一個元素的長度.${#array[*]}${#array[@]}表示數組中元素的個數

${#*}${#@} 表示位置參數的個數

 

2.1.8 對變量操作的總結

      # 表示求長度

      !表示求變量的名字

      # 表示開頭匹配 ,擴展 /# /% ## %% //

      % 表示結尾匹配

      / 表示求替換

      沒有/ 的都是刪除操作

3.1 內部命令和內建命令3.1.1  內建命令就是bash工具自帶的命令,大多和linux系統命令是一個名字。          設立內建命令的原因就是(1)內建命令不需要fork一個新的進程,可以執行的更快(2)內建命令可能會訪問bash的內核。          常用的內建命令,有:      3.1.1.1 I/O類                    echo                    printf                    read     3.1.1.2 文件類                    cd                    pwd                    pushd popd dirs  操作目錄棧      3.1.1.3 變量類                    let                    eval                    set  unset:set -r 受限shell restricted                    export                    declare typeset                    readonly                    getopts      3.1.1.4 腳本類                    .(source 命令)  , source是在主進程的環境下執行,. 是在進程的子進程下執行                   exit                   exec                   caller                   shopt      3.1.1.5 命令類                   true false                   type                   hash                   bind                   help       3.1.1.6 作業控制類                    作業不是進程                   jobs                   discown                   fg bg                   wait                   suspend                   logout                   times                   kill                   command                   builtin                   enable                   autload         3.1.1.7 比較類                   test                   [          3.1.1.8 函數類                   return          3.1.1.9 terminfo操作                  tput          3.1.1.10 數據類                  seq   3.2.1 子shell        子shell中的變量是局部變量,不能被父進程讀取。        進程在不同的子shell中可以串行地執行.這樣就允許把一個複雜的任務分成幾個小的子問題來同時地處理        在子shell中的目錄更改不會影響到父shell        子shell可用於爲一組命令設定臨時的環境變量        用"|"管道操作把I/O流重定向到子shell,例如ls -al | (command)     3.2.1.1 外部命令調用會產生一個子shell

    3.2.1.2( 命令1; 命令2; 命令3; ... )

              嵌在圓括號裏的一列命令在一個子shell裏運行    3.2.1.3 在一個花括號內的代碼塊不會運行一個子shell.

              { command1; command2; command3; ... }

    3.2.1.4 命令替換將會調用一個subshell :var=$() ; var=`do_action`

    3.2.1.5 & ,提交後臺作業

    3.2.1.6 管道

    3.2.1.7 . (source命令)或者file命令

    3.2.1.8 exec命令

    3.2.1.9 函數調用

3.2.2 受限shell

     #bin/bash -r   或者 set -r   shell運行在受限模式下

     這是一種安全策略, 目的是爲了限制腳本用戶的權限 , 受限shell模式下如下操作不能執行:

           使用cd 命令更改工作目錄.

           更改環境變量$PATH,$SHELL,$BASH_ENV,或$ENV 的值.           讀或更改shell環境選項變量$SHELLOPTS的值.           輸出重定向.           絕對路徑.           調用exec來把當前的受限shell替換成另外一個不同的進程.           腳本中許多其他無意中能破壞或搗亂的命令.           在腳本中企圖脫離受限shell模式的操作.

3.2.3 命令替換

          將一個命令的輸出賦值給某一個變量 。

          var=`do_action`  允許嵌套的,但要用\轉義``

          var=$(do_action)  允許嵌套的

          命令替換甚至允許將整個文件的內容放到變量中, 可以使用重定向或者cat命令。不要將2進制文件的內容保存到變量中

                 variable1=`<file1`      #  將"file1"的內容放到"variable1"中.   

                 variable2=`cat file2`   #  將"file2"的內容放到"variable2"中.    但是這行將會fork一個新進程

3.2.4 進程替換

          進程替換則是把一個進程的輸出回饋給另一個進程 (換句話說,它把一個命令的結果發送給另一個命令).

          進程替換的一般形式: 由圓括號括起的命令

>(command)

<(command)  在"<" 或or ">" 與圓括號之間是沒有空格的. 如果加了空格將會引起錯誤信息

進程替換能比較兩個不同命令之間的輸出:$ comm <(ls -l) <(ls -al) ;   diff <(ls $first_directory) <(ls $second_directory)

4.1 測試

      4.1.1 測試結構

               if  any_thing

               if test any_thing

               if  [ 空格分隔的變量 ]

               [ 空格分割的變量 ]     && ||  不能用在這個內建命令中  , 與 或 -a  -o

               if [[ ]]

               [[ ]]   與 或 && ||

               ((  )) 算術比較, 返回值和 [ ] 相反 

     4.1.2 文件類的比較

                -e     文件存在

                -f      文件是一個普通文件(不是一個目錄或是一個設備文件)                -s     文件大小不爲零                -d     文件是一個目錄                -b     文件是一個塊設備(軟盤, 光驅, 等等.)                 -c     文件是一個字符設備(鍵盤, 調制解調器, 聲卡, 等等.)                -p     文件是一個管道                -h     文件是一個符號鏈接                -L     文件是一個符號鏈接                -S     文件是一個socket                -t      文件(描述符)與一個終端設備相關

             這個測試選項可以用於檢查腳本中是否標準輸入 ([ -t 0 ])或標準輸出([ -t 1 ])是一個終端.

                 -r      文件是否可讀 (指運行這個測試命令的用戶的讀權限)                 -w     文件是否可寫 (指運行這個測試命令的用戶的讀權限)                 -x      文件是否可執行 (指運行這個測試命令的用戶的讀權限)                 -g      文件或目錄的設置-組-ID(sgid)標記被設置

             如果一個目錄的sgid標誌被設置,在這個目錄下創建的文件都屬於擁有此目錄的用戶組,而不必是創建文件的用戶所屬的組。這個特性對在一個工作組裏的同

             享目錄很有用處。

                 -u     文件的設置-用戶-ID(suid)標誌被設置

             一個root用戶擁有的二進制執行文件如果設置了設置-用戶-ID位(suid)標誌普通用戶可以以root權限運行。[1] 這對需要存取系統硬件的執行程序(比如說pppd

            和cdrecord)很有用。如果沒有設置suid位,則這些二進制執行程序不能由非root的普通用戶調用。

                 -O           你是文件擁有者                 -G           你所在組和文件的group-id相同                -N           文件最後一次讀後被修改                f1 -nt f2   文件f1f2                f1 -ot f2   文件f1f2                f1 -ef f2   文件f1f2 是相同文件的硬鏈接                !              "非" -- 反轉上面所有測試的結果(如果沒有給出條件則返回真).

    4.1.3  算術比較

               -eq  等於         if [ "$a" -eq "$b" ]

               -ne  不等於    if [ "$a" -ne "$b" ]

               -gt   大於        if [ "$a" -gt "$b" ]

               -ge  大於等於  if [ "$a" -ge "$b" ]

               -lt     小於       if [ "$a" -lt "$b" ]

               -le    小於等於 if [ "$a" -le "$b" ]

                <      小於(在雙括號裏使用)      (("$a" < "$b"))

                <=   小於等於 (在雙括號裏使用)(("$a" <= "$b"))

                >     大於 (在雙括號裏使用)      (("$a" > "$b"))

                >=   大於等於(在雙括號裏使用)(("$a" >= "$b"))

  4.1.4 字符串比較

       = ==等於            if [ "$a" = "$b" ]
       != 不相等 
           if [ "$a" != "$b" ]

  < 小於,依照ASCII字符排列順序

      if [[ "$a" < "$b" ]]   符號

      if [ "$a" \< "$b" ]    內建命令  所以 要轉義

       > 大於,依照ASCII字符排列順序

      if [[ "$a" > "$b" ]]

      if [ "$a" \> "$b" ]

       -z 字符串爲"null",即是指字符串長度爲零。     在測試方括號裏進行-n測試時一定要把字符串用引號起來,不然可能會出錯,可移植性不好       -n 字符串不爲"null",即長度不爲零            在測試方括號裏進行-n測試時一定要把字符串用引號起來,而且如果var有空格就不好辦   4.1.5  與 或       [ ]   中: -a -o        [[ ]] 中: && ||  ,  [[ ]] 比 [ ] 更常用

4.2  流程控制

    4.2.1  for

              2種形式: for var in action or $var-list

                               for(( a=2; a<var;a++ ))    c 風格 ,var沒有$

   4.2.2 while

             2種形式: while [ ] or [[ ]] or action

                              while((  a < var ))   c 風格,var沒有$

   4.2.3 util

            util [ ] or [[ ]] or action   until [[ condition ]] 是直到conditon 成立,纔不執行do done操作

   4.2.4 case

            case "$var_name" in               對變量使用""並不是強制的,因爲不會發生單詞分離

            “$case1”)

               do_sth

               ;;                                         case沒有break,沒有do done

           "$case2")

              do_sth

              ;;                                            case  沒有break,沒有do done

            esac

    4.2.5 select

           select var_name in $var_list

           do

              action

              break;

           done

   4.2.6 if [ ] 或 [[ ]] 或 action 或 test

            then

                do_sth

           else if [ ] [[ ]] test action        或者elif

           then

               do_sth

          else

                do_sth

         fi

         fi    注意, 有幾個fi就要有幾個fi  ; 上面如果使用elif,那麼下面只要一個fi就可以了  。

5.數組

    數組是多個變量的存儲,數組的變量時array[num], 等同於一般的變量var;  要訪問一個數組元素,可以使用花括號來訪問,即${array[xx]},0可以省略爲${array}

    數組元素沒有類型,不同類型的元素可以放在同一個數組裏

   5.1 數組定義

         declare -a array

        array =()          ()表明變量是數組

   5.2 數組初始化

      5.2.1 array[0]=$var  等同於變量賦值

      5.2.2 array=($var0 $var1 $var2 .....)

      5.2.3 array=([2]=$var [24]=$var)

  5.3 增加一個元素到數組                不同於c,數組可以擴展

     array=("$array[@]" "new1")  相當於,重新寫了扁數組中的所有元素

     array[${#array[@]}=new1

  5.4 調用數組

    5.4.1 ${array[@]} ${array[*]} 數組中的所有元素

             ${#array[@]} ${#array[*]}數組中元素個數

             ${array[num]} 數組中array[num]的值,

             ${array} 等同於 ${array[0]}

   5.4.2  ${array:pos:len} 數組從下標pos開始len個元素 , 即array[pos] array[pos+1]..array[pos+len-1]

             ${array[@]:0}  ${array[@]}  $array[*] 顯示數組的所有元素

   5.4.3  對數據某元素的調用

            ${array[N]:pos:len}  即 array[N]中,位置pos開始len個長度的字符

   5.4.4 刪除數組的某個元素

            unset array[N]  刪除array[N],等同於array[4]=

            unset array  等同於 unset array[@]  刪除整個數組

  5.5  複製數組

       array_2=($array[@])

       array_2=("$array[@]")  這個會保持數組中的分割符

  5.6 判斷索引是否在數組裏

      if [ "name" in array ]   不能用 if [ -z array[name] ] 

 

6.1 函數

    一個函數是一個子程序,用於實現一串操作的代碼塊(code block)

     6.1.1 func_name()

              {                               有更好的可移植性 , 符合c語言的格式

              }

             function func_name

             {

             } 

     6.1.2 傳給腳本的命令行參數怎麼辦?在函數內部可以看到它們嗎?

                 除非顯示的傳給函數參數,否則函數看不到傳給腳本的參數,例如看不到$1 $2 $3

     6.1.3 函數裏變量 和 參數 的作用域

        6.1.3.1 函數定義的變量默認是global的,其作用域從“函數"被調用時"執行變量定義的地方”開始,到shell結束或被顯示刪除處爲止            

                    函數定義的變量也可以被顯示定義成local的,其作用域侷限於函數內。

                    函數調用之前,所有在函數內聲明且沒有明確聲明爲local的變量都可在函數體外可見

         6.1.3.2  函數的參數是local的

         6.1.3.3  腳本中定義的變量是global的,其作用域從"被定義"的地方開始,到shell結束或被顯示刪除的地方爲止

     6.1.4 函數的返回值  $?  return的返回值也是寫到$?裏

              func xxx

              a=$?   不能寫成a=$(func xxx)

         6.1.4.1  return     內建命令 ,返回的最大正整數是255

                      如果沒有return ,將返回函數最後一個執行命令的退出狀態

          6.1.4.2 爲了函數可以返回字符串或是數組,用一個可在函數外可見的變量

          6.1.4.3 rerurn 返回的最大正整數是255 ,如何返回更大的數值

                      一種獲取大整數的"返回值"的辦法是簡單地將要返回的值賦給一個全局變量

                      更優雅的做法是在函數用 echo 打印"返回值到標準輸出",然後使用命令替換(command substitution)捕捉此值

     6.1.5 函數的輸入重定向

          函數本質上是一個代碼塊(code block), 這意味着它的標準輸入可以被重定向

         Function ()    {     ...    } < file    # 也試一下這個:   Function ()    {     {       ...      } < file  }

7.1 內部變量

      OFS=\r\n

8.1 常用命令

     find

     rev

     md5sum

     printf printf “ string  %d %u %s ”  $var1 $var2 $var3

     head   head filename -n N 打印頭N行 ; head filename -n -N 打印頭N行之後的所有行

     tail     tail filename -n M 打印結尾M行; tail filename -n +M 打印頭M行之後的所有行

     bc     hex=`echo "obase=16;ibase=10; $n" | bc`   十進制轉化爲16進制  ; echo $1+$2 | bc 浮點數計算

     tput  光標屬性

     tput cup row_num col_num  將光標移到 row行 col列位置

     tput cols  查看當前串口tty的列寬col

     date +%a +%A +%b +%B 顯示當前的時間,不同的顯示格式 。  man date

9.1 全局變量

   $LOGNAME

 

發佈了11 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章