Linux Shell常用技巧(十一) 交互式使用shell

Linux Shell常用技巧(十一) 交互式使用shell

二十二. 交互式使用Bash Shell:

    1.  用set命令設置bash的選項:
    下面爲set主要選項的列表及其表述:

選項名開關縮寫描述
allexport-a打開此開關,所有變量都自動輸出給子Shell。
noclobber-C防止重定向時文件被覆蓋。
noglob-d在路徑和文件名中,關閉通配符。


    #打開該選項
    /> set -o allexport   #等同於set -a
    #關閉該選項
    /> set +o allexport  #等同於set +a
    #列出當前所有選項的當前值。
    /> set -o
    allexport         off
    braceexpand   on
    emacs             on
    errexit            off
    errtrace          off
    functrace        off
    hashall            on
    histexpand      on
    ... ...
    /> set -o noclobber     #打開noclobber選項,防止在重定向時原有文件被覆蓋。
    /> date > outfile         #通過date命令先生成一個文件outfile。
    /> ls > outfile             #將ls命令的輸出重定向到該文件outfile,shell將提示不能覆蓋已經存在的文件。
    -bash: outfile: cannot overwrite existing file
    /> set +o noclobber    #關閉noclobber選項。
    /> ls > outfile             #重新將ls的輸出重定向到outfile,成功。


    2.  變量:
    設置局部變量:
    /> name="stephen liu"  #注意等號兩邊不要有空格,如果變量值之間存在空格,則需要用雙引號括起
    /> echo $name
    stephen liu
    /> name=                    #將變量設置爲空時,等號後面也不要有空格,直接回車即可。
    /> echo $name             #name變量爲空,因此echo不會有任何輸出。
    注意:以上變量的聲明方式均可替換爲declare variable=value的形式。

    /> declare name="stephen liu"
    /> readonly name         #將name變量設置爲只讀。
    /> echo $name
    stephen liu
    /> name="my wife"      #如果針對只讀變量重新賦值,將報錯,提示name是隻讀變量。
    -bash: name: readonly variable
    /> unset name             #如果unset只讀變量,將同樣報錯,提示不能unset只讀變量。
    -bash: unset: name: cannot unset: readonly variable

    設置全局/環境變量:
    在當前Shell中創建的全局/環境變量可以直接傳遞給它所有的子Shell,當前創建環境變量的Shell被稱爲夫Shell。
    /> export allname=john         #利用export命令,將其後聲明的變量置爲環境變量
    /> bash                                #啓動一個新的子Shell
    /> echo $allname                  #在子Shell中echo變量$allname,發現夫Shell中設置的值被傳遞到子Shell
    john
    /> declare -x allname2=peter #這裏的功能和結果都是和上面的命令相同,只是利用declare -x命令設置環境變量
    /> bash
    /> echo $allname2
    peter

    下面的列表將給出常用的內置Shell環境變量:

變量名含義
BASH表示bash命令的完整路徑名。
ENV在啓動新bash shell時執行的環境文件名。
HOME主目錄。
LANG本地化語言。
PATH命令搜索路徑,彼此之間冒號分隔。
PPID父進程PID。
PWD當前工作目錄,用cd命令設置。


    3.  echo命令:
    該命令主要用於將其參數打印到標準輸出。其中-e選項使得echo命令可以無限制地使用轉義序列控制輸出的效果。下面的列表給出常用的轉義序列。

轉義序列功能
\c不換行打印
\n換行
\t製表符
\\反斜槓

    echo還提供了一個常用的-n選項,其功能不輸出換行符。

    /> echo The username is $LOGNAME
    The username is stephen
    #下面命令的輸出中的“/>”表示命令行提示符。
    /> echo -e "\tHello World\c"
        Hello World />
    /> echo -n "Hello World"
    Hello World />

    4.  printf命令:
      該命令和C語言中的printf函數的功能相同,都用用來格式化輸出的。格式包括字符串本身和描述打印效果的字符。定義格式的方法和C語言也是完全一樣 的,即在%後面跟一個說明符,如%f表示後面是一個浮點數,%d表示一個整數。printf命令也同樣支持轉義序列符,其常用轉義序列如下:

轉義序列功能
\c不換行打印
\n換行
\t製表符
\\反斜槓
\"雙引號

    其常用的格式化說明符列表如下:

說明符描述
%cASCII字符
%d,%i十進制整數
%f浮點格式
%o不帶正負號的八進制值
%s字符串
%u不帶正負號的十進制值
%x不帶正負號的十六進制值,其中使用a-f表示10-15
%X不帶正負號的十六進制值,其中使用A-F表示10-15
%%表示%本身

    下面是printf的一些常用使用方式:
    /> printf "The number is %.2f.\n" 100   這裏.2f表示保留小數點後兩位
    The number is 100.00.
    #%-20s表示一個左對齊、寬度爲20個字符字符串格式,不足20個字符,右側補充相應數量的空格符。
    #%-15s表示一個左對齊、寬度爲15個字符字符串格式。
    #%10.2f表示右對齊、10個字符長度的浮點數,其中一個是小數點,小數點後面保留兩位。
    /> printf "%-20s%-15s%10.2f\n" "Stephen" "Liu" 35
    Stephen             Liu                 35.00
    #%10s表示右對齊、寬度爲10的字符串,如不足10個字符,左側補充相應數量的空格符。
    /> printf "|%10s|\n" hello
    |     hello|
    在printf中還有一些常用的標誌符,如上面例子中的符號(-),這裏我們再介紹一個比較常用的標識符"#"
    #如果#標誌和%x/%X搭配使用,在輸出十六進制數字時,前面會加0x/0X前綴。
    /> printf "%x %#x\n" 15 15
    f 0xf


   5.  變量替換運算符:
    bash中提供了一組可以同時檢驗和修改變量的特定修改符。這些修改符提供了一個快捷的方法來檢驗變量是不是被設置過,並把輸出結果輸出到一個變量中,見下表:

修改符描述用途
${variable:-word}如variable被設置且非空,則返回該值,否則返回word,變量值不變。如變量未定義,返回默認值。
${variable-word}如variable未被設置,則返回word,變量值不變,如果設置變量,則返回變量值,即使變量的值爲空值。如變量未設置,返回默認值。
${variable:=word}如variable被設置且非空,則返回該值,否則設置變量爲word,同時返回word。如果變量未定義,則設置其爲默認值。
${variable=word}如variable未設置,則設置變量爲word,同時返回word,如果variable被設置且爲空,將返回空值,同時variable不變。否則返回variable值,同時variable不變。如果變量未設置,則設置其爲默認值。
${variable:+word}如variable被設置且非空,則返回word,否則返回null,變量值不變。用於測試變量是否存在。
${variable+word}如variable被設置(即使是空值),則返回word,否則返回空。用於測試變量是否設置。
${variable:?word}如variable被設置且非空,則返回該值,否則顯示word,然後退出Shell。如果word爲空,打印"parameter null or not set"爲了捕捉由於變量未定義所導致的錯誤。
${variable:offset}從variable的offset位置開始取,直到末尾。
${variable:offset:length}從variable的offset位置開始取length個字符。


    #${variable:-word}的示例,其C語言表示形式爲:
    #    if (NULL == variable)
    #        return word;
    #    else
    #        return $variable;
    /> unset var_name                        #將變量var_name置爲空。
    /> var_name=
    /> echo ${var_name:-NewValue}    #var_name爲空,因此返回NewValue
    NewValue
    /> echo $var_name                        #var_name的值未變化,仍然爲空。

    /> var_name=OldValue                   #給var_name賦值。
    /> echo ${var_name:-NewValue}    #var_name非空,因此返回var_name的原有值。
    OldValue
    /> echo $var_name                        #var_name的值未變化,仍然OldValue。
    OldValue

    #${variable-word}的示例,其僞碼錶示形式爲
    #    if (variable is NOT set)
    #        return word;
    #    else
    #        return $variable;
    /> unset var_name                         #取消該變量var_name的設置。
    /> echo ${var_name-NewValue}    #var_name爲空,因此返回NewValue
    NewValue
    /> echo $var_name                        #var_name的值未變化,仍然爲空。

    /> var_name=OldValue                   #給var_name賦值,即便執行var_name=,其結果也是一樣。
    /> echo ${var_name-NewValue}    #var_name非空,因此返回var_name的原有值。
    OldValue
    /> echo $var_name                        #var_name的值未變化,仍然OldValue。
    OldValue

    
    #${variable:=word}的示例,其C語言表示形式爲:
    #    if (NULL == variable) {
    #        variable=word;
    #        return word;
    #    } else {
    #        return $variable;
    #    }
    /> unset var_name                        #將變量var_name置爲空。
    /> var_name=
    /> echo ${var_name:=NewValue}   #var_name爲空,設置變量爲NewValue同時返回NewValue。
    NewValue
    /> echo $var_name                        #var_name的值已經被設置爲NewValue。
    NewValue
    /> var_name=OldValue                  #給var_name賦值。
    /> echo ${var_name:=NewValue}   #var_name非空,因此返回var_name的原有值。
    OldValue
    /> echo $var_name                       #var_name的值未變化,仍然OldValue。
    OldValue
    
    #${variable=word}的示例,其僞碼錶示形式爲:
    #    if (variable is NOT set) {
    #        variable=word;
    #        return word;
    #    } else if (variable == NULL) {
    #        return $variable;  //variable is NULL
    #    } else {
    #        return $variable;
    #    }
    /> unset var_name                        #取消該變量var_name的設置。
    /> echo ${var_name=NewValue}  #var_name未被設置,設置變量爲NewValue同時返回NewValue。
    NewValue
    /> echo $var_name                        #var_name的值已經被設置爲NewValue。
    NewValue
    /> var_name=                              #設置變量var_name,並給該變量賦空值。
    /> echo ${var_name=NewValue}  #var_name被設置,且爲空值,返回var_name的原有空值。
   
    /> echo $var_name                       #var_name的值未變化,仍未空值。
   
    /> var_name=OldValue                  #給var_name賦值。
    /> echo ${var_name=NewValue}  #var_name非空,因此返回var_name的原有值。
    OldValue
    /> echo $var_name                       #var_name的值未變化,仍然OldValue。
    OldValue

    #${variable:+word}的示例,其C語言表示形式爲:
    #    if (NULL != variable)
    #        return word;
    #    else
    #        return $variable;
    /> var_name=OldValue                  #設置變量var_name,其值爲非空。
    /> echo ${var_name:+NewValue}   #由於var_name有值,因此返回NewValue
    NewValue
    /> echo $var_name                       #var_name的值仍然爲遠之OldValue
    OldValue
    /> unset var_name                        #將var_name置爲空值。
    /> var_name=
    /> echo ${var_name:+NewValue}   #由於var_name爲空,因此返回null。
    /> echo $var_name                       #var_name仍然保持原有的空值。

    #${variable+word}的示例,其僞碼錶示形式爲
    #    if (variable is set)
    #        return word;
    #    else
    #        return $variable;
    /> var_name=OldValue                  #設置變量var_name,其值爲非空。
    /> echo ${var_name+NewValue}   #由於var_name有值,因此返回NewValue
    NewValue
    /> echo $var_name                       #var_name的值仍然爲遠之OldValue
    OldValue
    /> unset var_name                        #取消對變量var_name的設置。
    /> echo ${var_name+NewValue}   #返回空值。
    /> echo $var_name                       #var_name仍未被設置。

    #${variable:?word}的示例,其C語言表示形式爲:
    #    if (NULL != variable) {
    #        return variable;
    #    } else {
    #        if (NULL != word)
    #            return "variable : word";
    #        else
    #            return "parameter null or not set";
    #    }
    /> var_name=OldValue                  #設置變量var_name,其值爲非空。
    /> echo ${var_name:?NewValue}   #由於var_name有值,因此返回變量的原有值
    OldValue
    /> unset var_name                        #將var_name置爲空值。
    /> var_name=
    /> echo ${var_name:?NewValue}   #由於var_name爲空,因此返回word。
    -bash: var_name: NewValue
    /> echo $var_name                       #var_name仍然保持原有的空值。

    /> echo ${var_name:?}                #如果word爲空,返回下面的輸出。
    -bash: var_name: parameter null or not set

    #${variable:offset}示例:
    /> var_name=notebook
    /> echo ${var_name:2}
    tebook
    /> echo ${var_name:0}                #如果offset爲0,則取var_name的全部值。
    notebook

    ${variable:offset:length}示例:
    /> var_name=notebook
    /> echo ${var_name:0:4}
    note
    /> echo ${var_name:4:4}
    book

    6.  變量模式匹配運算符:
    Shell中還提供了一組模式匹配運算符,見下表:

運算符替換
${variable#pattern}如果模式匹配變量值的開頭,則刪除匹配的最短部分,並返回剩下的部分,變量原值不變。
${variable##pattern}如果模式匹配變量值的開頭,則刪除匹配的最長部分,並返回剩下的部分,變量原值不變。
${variable%pattern}如果模式匹配變量值的結尾,則刪除匹配的最短部分,並返回剩下的部分,變量原值不變。
${variable%%pattern}如果模式匹配變量值的結尾,則刪除匹配的最長部分,並返回剩下的部分,變量原值不變。
${#variable}返回變量中字母的數量。


    #${variable#pattern}示例:
    /> pathname="/home/stephen/mycode/test.h"
    /> echo ${pathname#/home}        #變量pathname開始處匹配/home的最短部分被刪除。
    /stephen/mycode/test.h
    /> echo $pathname                       #pathname的原值不變。
    /home/stephen/mycode/test.h

    #${variable##pattern}示例:
    /> pathname="/home/stephen/mycode/test.h"
    /> echo ${pathname##*/}            #變量pathname開始處匹配*/的最長部分被刪除,*表示任意字符。
    test.h
    /> echo $pathname                       #pathname的原值不變。
    /home/stephen/mycode/test.h

    #${variable%pattern}示例:
    /> pathname="/home/stephen/mycode/test.h"
    /> echo ${pathname%/*}             #變量pathname結尾處匹配/*的最短部分被刪除。
    /home/stephen/mycode
    /> echo $pathname                       #pathname的原值不變。
    /home/stephen/mycode/test.h

    #${variable%%pattern}示例:
    /> pathname="/home/stephen/mycode/test.h"
    /> echo ${pathname%%/*}          #變量pathname結尾處匹配/*的最長部分被刪除,這裏所有字符串均被刪除。

    /> echo $pathname                       #pathname的原值不變。
    /home/stephen/mycode/test.h

    #${#variable}示例:
    /> name="stephen liu"
    /> echo ${#name}
    11

    7.  Shell中的內置變量:
    Shell中提供了一些以$開頭的內置變量,見下表:

變量名描述
$?表示Shell命令的返回值
$$表示當前Shell的pid
$-表示當前Shell的命令行選項
$!最後一個放入後臺作業的PID值
$0表示腳本的名字
$1--$9表示腳本的第一到九個參數
${10}表示腳本的第十個參數
$#表示參數的個數
$*,$@表示所有的參數,有雙引號時除外,"$*"表示賦值到一個變量,"$@"表示賦值到多個。

    所有的內置變量都比較容易理解,因此這裏僅給出$*和$@的區別用法:
    /> set 'apple pie' pears peaches
    /> for i in $*
    >  do
    >  echo $i
    >  done
    apple
    pie
    pears
    peaches

    /> set 'apple pie' pears peaches
    /> for i in $@
    >  do
    >  echo $i
    >  done
    apple
    pie
    pears
    peaches


    /> set 'apple pie' pears peaches
    /> for i in "$*"           #將所有參數變量視爲一個
    >  do
    >  echo $i
    >  done
    apple pie pears    peaches
    
    /> set 'apple pie' pears peaches
    /> for i in "$@"
    >  do
    >  echo $i
    >  done
    apple pie                   #這裏的單引號將兩個單詞合成一個.
    pears
    peaches    
   
    8.  引用:
    Shell中提供三種引用字符,分別是:反斜槓、單引號和雙引號,它們可以使Shell中所有元字符失去其特殊功能,而還原其本意。見以下元字符列表:

元字符描述
;命令分隔符
&後臺處理Shell命令
()命令組,創建一個子Shell
{}命令組,但是不創建子Shell
|管道
< >輸入輸出重定向
$變量前綴
*[]?用於文件名擴展的Shell通配符

    注:單引號和雙引號唯一的區別就是,雙引號內可以包含變量和命令替換,而單引號則不會解釋這些,見如下示例:
    /> name=Stephen
    /> echo "Hi $name, I'm glad to meet you! "  #name變量被替換
    Hi Stephen, I'm glad to meet you!
    /> echo 'Hi $name, I am glad to meet you! ' #name變量沒有被替換
    Hi $name, I am glad to meet you!
    /> echo "Hey $name, the time is $(date)"      #name變量和date命令均被替換
    Hey Stephen, the time is Fri Nov 18 16:27:31 CST 2011
    /> echo 'Hey $name, the time is $(date)'
    Hey $name, the time is $(date)                      #name變量和date命令均未被替換

    9.  命令替換:
    同樣我們需要把命令的輸出結果賦值給一個變量或者需要用字符串替換變量的輸出結果時,我們可以使用變量替換。在Shell中,通常使用反引號的方法進行命令替換。
    /> d=`date`                           #將date命令的執行結果賦值給d變量。
    /> echo $d
    Fri Nov 18 16:35:28 CST 2011
    /> pwd
    /home/stephen
    /> echo `basename \`pwd\``  #基於反引號的命令替換是可嵌入的,但是嵌入命令的反引號需要使用反斜槓轉義。
    stephen
    除了反引號可以用於命令替換,這裏我們也可以使用$(command)形式用於命令替換。
    /> d=$(date)
    /> echo $d
    Fri Nov 18 16:42:33 CST 2011
    /> dirname="$(basename $(pwd))"     #和之前的反引號一樣,該方式也支持嵌套。
    /> echo $dirname
    stephen

   10.  數學擴展:
    Shell中提供了兩種計算數學表達式的格式:$[ expression ]和$(( expression ))
    /> echo $[5+4-2]
    7
    /> echo $[5+2*3]
    11
    /> echo $((5+4-2))
    7
    /> echo $((5+2*3))
    11    
    事實上,我們也可以在Shell中聲明數值型的變量,這需要在declare命令的後面添加-i選項,如:
    /> declare -i num
    /> num=5+5      #注意在賦值的過程中,所有的符號之間均沒有空格,如果需要空格,需要在表達式的外面加雙引號
    /> echo $num    #如果沒有聲明declare -i num,該命令將返回5+5
    10
    /> num="5 * 5"
    /> echo $num
    25
    /> declare strnum
    /> strnum=5+5
    /> echo $strnum #由於並未將strnum聲明爲數值型,因此該輸出將按字符串方式處理。
    5+5
    Shell還允許我們以不同進制的方式顯示數值型變量的輸出結果,其格式爲:進制+#+變量。
    /> declare -i x=017 #017其格式爲八進制格式
    /> echo $x           #缺省是十進制
    15
    /> x=2#101         #二進制
    /> echo $x
    5
    /> x=8#17           #八進制
    /> echo $x
    15
    /> x=16#b           #十六進制
    /> echo $x
    11
    在Shell中還提供了一個內置命令let,專門用於計算數學運算的,見如下示例:
    /> let i=5
    /> let i=i+1
    /> echo $i
    6
    /> let "i = i + 2"
    /> echo $i
    8
    /> let "i+=1"
    /> echo $i
    9    

    11.  數組:
      Shell中提供了創建一維數組的能力,你可以把一串數字、名字或者文件放在一個變量中。使用declare的-a選項即可創建它們,或者在變量後面增 加下標操作符直接創建。和很多其它開發語言一樣,Shell中的數組也是0開始的,然而不同的是Shell中數組的下標是可以不連續的。獲取數組中某個元 素的語法格式爲: ${arrayname[index]}。見如下示例:
    /> declare -a friends                   #聲明一個數組變量
    /> friends=(sheryl peter louise)   #給數組變量賦值
    /> echo ${friends[0]}                #通過數組下標的方式訪問數組的元素
    sheryl
    /> echo ${friends[1]}
    peter
    /> echo ${friends[2]}
    louise
    /> echo ${friends[*]}                #下標中星號表示所有元素。
    shery1 peter louise
    # ${#array[*]}表示數組中元素的數量,而${#friend[0]}則表示第一個元素的長度。
    /> echo ${#friends[*]}    
    3
    /> unset friends                         #unset array清空整個數組,unset array[index]僅清空指定下標的元素。

    /> x[3]=100
    /> echo ${x[*]}
    100
    /> echo ${x[0]}                        #0下標的元素並沒有被賦值過,因爲輸出爲空。

    /> echo ${x[3]}
    100
    /> states=(ME [3]=CA [2]=CT)   #ME的下標爲0。
    /> echo ${states[0]}
    ME
    /> echo ${states[1]}                 #數組下標爲1的位置沒有被賦值過,因此沒有輸出。

    /> echo ${states[2]}
    CT
    /> echo ${states[3]}
    CA

    12.  函數:
    和C語言一樣,Shell中也可以創建自己的自定義函數。其格式如下:
    function_name () { commands; commands; }
    function function_name { commands; commands; }
    function function_name () { commands; commands; }
    函數的參數在函數內是以$[0-9]、${10}...,這種局部變量的方式來訪問的。見下面的示例:

    #函數的左花括號和命令之間必須有至少一個空格。每個命令的後面都要有一個分號,即便是最後一個命令
    /> function greet { echo "Hello $LOGNAME, today is $(date)"; }
    #此時函數已經駐留在當前的bash shell中,因此使用函數效率更高。
    /> greet   
    Hello root, today is Fri Nov 18 20:45:10 CST 2011
    /> greet() { echo "Hello $LOGNAME, today is $(date)"; }
    /> greet
    Hello root, today is Fri Nov 18 20:46:40 CST 2011
    #welcome函數內部使用了函數參數。
    /> function welcome { echo "Hi $1 and $2"; }
    /> welcome stephen jane    
    Hi stephen and jane
    #declare -F選項將列出當前Shell中駐留的函數
    /> declare -F
    declare -f greet
    declare -f welcome
    #清空指定的函數,使其不在Shell中駐留。
    /> unset -f welcome

    13.  重定向:
    下面的列表爲Shell中支持的重新定向操作符。

操作符功能
<重新定向輸入
>重新定向輸出
>>追加輸出
2>重新定向錯誤
&>重新定向錯誤和輸出
>&重新定向錯誤和輸出
2>&1重新定向錯誤到標準輸出
1>&2重新定向標準輸出到錯誤
>|重新定向輸出的時候覆蓋noclobber選項


    #find命令將搜索結果輸出到foundit文件,把錯誤信息輸出到/dev/null
    /> find . -name "*.c" -print > foundit 2> /dev/null
    #將find命令的搜索結果和錯誤信息均輸出到foundit文件中。
    /> find . -name "*.c" -print >& foundit
    #同上。
    /> find . -name "*.c" -print > foundit 2>&1
    #echo命令先將錯誤輸出到errfile,再把信息發送到標準錯誤,該信息標準錯誤與標準輸出合併在一起(errfile中)。
    /> echo "File needs an argument" 2> errfile 1>&2
    /> cat errfile
    File needs an argument


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章