2011年9月7日 星期三

shell script po文測試標題

一 基本觀念
1. 回應目前所使用的shell為何?
  $echo $SHELL
2. 通配符號
  ? 任何一個字符
  * 任何字符(一串字符)
  [set] 在set中的任何字符
  [!set] 不在set中的任何字符
3. 大括弧擴展
  {,{,},}
  ex. echo b{ed,olt,ar}s   結果列印 beds bolts bars
  ex. echo b{ar{d,n,k},ed}s 結果列印bards barns barks beds
  ex. echo {d..h} 結果看到 d e f g h  
  至少要有一個逗號 否則所產生的單字會維持原狀 ex. b{o}lt 還是被當成b{o}lt
 
4. 背景執行
  指令後面加&
 
5. 檢視背景執行
  $jobs
 
6. nice command
  $nice command
  command 以比較低的優先權處理
7. 特殊字符與加引號
  ~ 主目錄
  ` 命令替換(舊式)
  # 註解
  $ 變數表示示
  & 背景工作
  * 字串通配符
  ( 啟動subshell
  ) 終止subshell
  \ 引述下一個字符
  | 導管
  [ 起始字符集通配符
  ] 終止字符集通配符
  { 起始命令區塊
  } 終止命令區塊
  ; shell命令之區隔符
  ' 強引號
  " 弱引號
  < 輸入轉向
  > 輸出轉向
  / 路徑名稱之目錄區隔符
  ? 單字符通配符
  ! 管線之邏輯NOT算符
 
8. 去除特殊字符的字面意義
  a.)加單引號(quoting)---
  去除特殊字符的字面意義
  ex. $echo '2 * 3 > 5 is a valid inequality.'

  b.)以倒斜線規避
  ex. $echo 2 \* 3 \> 5 is a valid inequality.

9. 控制鍵
  控制鍵    相應的stty名稱    功能
  ^C        intr              結束現行命令
  ^D        eof               結束輸入
  ^\        quit              結束現行命令,如果CTRL-C管用的話
  ^S        stop              停止輸出到螢幕上
  ^Q                          開始輸出到螢幕上
  ^?或DEL   erase             刪除最後一個字符
  ^U        kill              刪除整個命令列
  ^Z/^Y     susp              暫停現行的命令
  ^W                          werase
  ^R                          rprnt
  ^O                          flush
  ^V                          lnext
  可以使用stty -a 查看設定


二 編輯命令列
emacs 編輯模式
1. 基本指令
^B  將游標往後(backward)移一個字符(不會進行刪除動作)
^F  將游標往前(forward)移一個字符
DEL 往後(backward)刪除一個字符
^D  往前(forward)刪除一個字符

2. 單字處理命令
ESC-B   將游標往後(backward)移動一個單字
ESC-F   將游標往前(forward)移動一個單字  
ESC-DEL 往後刪除(kill)一個單字
ESC-^-H 往後刪除一個單字
ESC-D   往前刪除一個單字
^-Y     取回(yank)上一次所刪除的項目

3. 列處理命令
^-A   移到列的開頭
^-E   移到列的結尾
^-K   往前刪除一整列

4. 在歷程檔中遊走
^-P     移到上一頁
^-N     移到下一頁
^-R     往回搜尋
ESC-<   移到歷程的第一列
ESC->   移到歷程的最後一列

5. 文字補全
tab     試圖進行一般的補全功能
ESC-?   列出可能的補全結果

ESC-/   試圖補全檔案名稱
^-X/    列出可能的『檔案名稱』補全結果
ESC-~   試圖補全用戶名稱
^-X~    列出可能的『用戶名稱』補全結果
ESC-$   試圖補全變數
^-X$    列出可能的變數補全結果
ESC-@   試圖補全主機名稱
^-X@    列出可能的『主機名稱』補全結果
ESC-!   試圖補全命令
^-X!    列出可能的『命令』補全結果
ESC-TAB 試圖以歷程紀錄(history list)中之前所鍵入的命令進行補全

6. 雜項命令
^-J     同RETURN
^-L     清除螢幕,將現行(current)列置於螢幕頂端
^-M     同RETURN
^-O     同RETURN,但會接著顯示命令歷程中的下一列
^-T     將標點兩邊的字符對調,並將標點向右移動一個位置
^-U     刪除從列的開頭到標點為止的部份
^-V     未下一個字符加上引號(規避該字符的特殊意義,如果有特殊意義的話)
^-[     同ESC(適用於大多數鍵盤)
^-C     將標點右邊的單字(word)換成大寫字母開頭
^-U     將標點右邊的單字全部換成大寫字母
^-L     將標點右邊的單字全部換成小寫字母
ESC-.   在標點右邊插入上一道命令列的最後一個單字
ESC-_   同ESC-.


vi 編輯模式

0. vi輸入模式的編輯命令
del   刪除前一個字
^-w   刪除前一個單字
^-v   為下一個字符加上引號
esc   進入控制模式

以下所有命令都可以前置一個數字(n)做為重複次數
1. 簡單的控制模式命令
h   往左移一個字 (與編輯時^+H有關)
l   往右移一個字
w   往右移一個單字
b   往左移一個單字
W   移到下一個非空白單字的開頭
B   移到前一個非空白單字的開頭
e   移到現行單字的末端
E   移到現行非空白單字的末端
0(zero) 移到一列之首
^   移到一列之第一個非空白字符
$   移到一列的的末端

2.  鍵入和更改文字

i    字前插入文字(插入)
a    字後插入文字(添加)
I = 0i    列首插入文字
A = $a    列尾插入文字
R       覆蓋既有文字(Replace in edit mode)
(n)r    覆蓋既有文字(command)

3. 刪除命令
用c替代d,會在做完刪除後進入輸入模式
dh    往左刪除一個字
dl    往右刪除一個字
db    往左刪除一個單字
dw    往右刪除一個單字
dB    往左刪除一個非空白單字
dW    往右刪除一個非空白單字
d$    一直刪除到行尾端
d0    一直刪除到行開端

D = d$
dd = 0d$
C = c$
cc = 0c$
X = dh
x = dl

u    undo(undelete)
.    重複上次文字修改命令
y(yank)    擷取
p    文字插入在字的右邊
P    文字插入在字的左邊

4. 在歷史檔中遊走

k = -    往後移動一列
j = +    往前移動一列 (與編輯時^+J有關)
G = gg    移動到重複次數所指定的命令列
/string    往後搜尋字串string
?string    往前搜尋字串string
n    依上次搜尋方向重複搜尋
N    依上次搜尋反方向重複搜尋

5. 尋找字符命令
fn    向右移動到下一個n所在位置
Fn    向左移動到前一個n所在位置
tn    fn+移回一格
Tn    Fn+往前移一格
|

三. 訂製你的環境
1. 啟動檔: .bash_profile .bash_logout .bashrc
    登入系統檔案尋找順序(找不到檔案便會往下一個檔案找): .bash_profile -> .bash_login -> .profile
    離開login shell :會執行.bash_logout
    .bash_profile只會被login shell    所讀取與執行。如果在命令列上以鍵入bash的方式啟動一個新的shell(一個shushell),它會試圖從.bashrc檔中讀取命令。
2. 別名:
    alias name='command' or command    //=兩邊不能有空格
    可以替別名取另一個別名,也就是別名可以遞迴定義。
   
    alias listfile=ls
    alias ls=listfile  //那麼別名listfile將會被略過不計。
   
    bash隱晦功能:如果一個別名的值(等號的右邊部分)是以一個空格結束的,那麼bash便會對命令列的下一個單字進行別名替換。要讓別名的值以空格結束,得要為它加上引號。

    alias name 或 alias : 會列出別名設定。
3. 選項:
    set -o optionname (開啟option) 和 set +o optionname(關閉option)
    3.1 shopt
        -p 列出可設定的shell選項以及他們目前的設定值。
        -s 設定(set)或開啟每個選項名稱。
        -u 取消(unset)或關閉每個選項名稱。
        -q 抑制正常輸出;傳回狀態會指出一個變數是否有被設定。
        -o 允許選項名稱的值成為set命令以-o選項所定義的值。

4. shell變數:
    varname='value' or value //=兩邊不能有空格
    變數使用$varname
    查看變數值 可使用echo $varname
    4.1 變數以及加引號
        雙引號裡的特殊字符會被shell解釋
        單引號裡的特殊字符完全不會遭到shell的解釋
    4.2 內建變數
        4.2.1 編輯模式變數

        4.2.2 郵件變數
            MAIL    郵件檔的名稱,用以檢查有無新收到的郵件
              郵件檔 /usr/mail/yourname
              只要設定 MAIL=/usr/mail/yourname 就行了。

            MAILCHECK    多久檢查一次新郵件,以秒為單位(預設60秒)
            MAILPATH    郵件檔名單,以冒號(:)為分隔符,用來檢查新收到的郵件。
              ex.     MAILPATH=/usr/mail/you/martin:/usr/mail/you/geoffm:/usr/mail/you/paulr
                      MAILPARH="\
                      /usr/mail/you/martin?you have mail from Martin.:\
                      /usr/mail/you/geoffm?Mail from Geoff has arrived.:\
                      /usr/mail/you/paulr?There is new mail from Paul."
            $_ 顯示幕前的郵件檔名稱

        4.2.3 提示變數
            分別存放在PS1 PS2 PS3 PS4
            提示字串的制定命令
            \a    ASCII的響鈴(bell)字符(007)
            \A    採用24小時制,以HH:MM的格式來顯示現在的時間
            \d    以Weekday Month Day的格式來顯示日期
            \D{format}    format會被傳入strftime(3),所產生的結果會被插入提示字串;如果format為空值,則會以語系特定的格式來顯示時間
            \e    ESC(033)
            \H    主機名稱
            \h    主機名稱中第一個.之前的部分
            \j    shell目前所控管的工作數量
            \l    shell之終機端名稱的基本名稱(basename)
            \n    LR+LF
            \r    LR
            \s    shell的名稱
            \T    採用12小時制,以HH:MM:SS的格式來顯示現在的時間
            \t    以HH:MM:SS的格式來顯示現在的時間
            \@    採用12小時制,以am/pm的格式來顯示現在的時間
            \u    現行使用者的用戶名稱
            \v    bash的版本 ex.2.00
            \V    bash的發行版本;版本和修補次數 ex.2.00.0
            \w    現行工作目錄
            \W    現行工作目錄的基本名稱(basename)
            \#    現行命令的命令編號
            \!    現行命令的歷程編號
            \$    如果有效的UID是0,就顯示一個"#"符號,否則就顯示一個"$"符號
            \nnn    八進制的字符碼
            \\    顯示一個到斜線
            \[    非列印(non-printing)字符序列的開頭,像是終端機的控制序列
            \]    非列印(non-printing)字符序列的結尾。

        4.2.4 命令的搜尋路徑
            在.bash_profile加入PATH: PATH=$PATH:"/home/you/bin"

        4.2.5 將命令的路徑存入雜湊表
            hash 查看雜湊表內容
            hash -r    移除hash的一切
            hash -d    name    移除特定的命令名稱
            hash -p namepath    加入特定的命令路徑
           
            使用set 指定hashall 選項開關hash

        4.2.6 目錄的搜尋路徑和變數
            CDPATH 值如同PATH
                空字串代表現行目錄

        4.2.7 雜項變數
            HOME    你的主機(登入)目錄名稱
            SECONDS    shell被調用之後所持續的秒數
            BASH    你所執行之shell的路徑名稱
            BASH_VERSION    你所執行之shell的版本編號
            BASH_VERSINFO    你所執行之shell的版本資訊陣列
            PWD    現行目錄
            OLDPWD    執行上一次cd命令之前所在的目錄
    5. 定製與子行程
        5.1 環境變數
            export varnames
            export or export -p 察看環境變數

            TERM=trythisone emacs filename

四. shell 程式設計基礎

    1. shell 命令稿與函式
        執行script方法:
                    1. source scriptname
                    2. 鍵入檔案名稱+enter
        ./scriptname :相當於鍵入命令稿的絕對路徑
        透過名稱調用命令稿之前需要先賦予它執行權

        差異:
            source scriptname    shell:        ---->--script-->---->    在同一個shell上執行script

            scriptname            shell:        ---->           ---->    shell等待subshell執行完script後繼續執行
                                subshell:         --script-->        在subshell上執行script

            scriptname&            shell:        ---->...........---->    subshell執行同時shell繼續執行(subshell在背景執行)
                                subshell         --script-->        在背景subshell執行script

        1.1 函式
            表示方式:
            1.
            function functname
            {
              shell commands
            }
            或
            2.
            functname ()
            {
              shell commands
            }

            可以使用unset -f functname 刪除某個函式的定義
            declare -f :查看登入時間定義了那些函式
            declare -F :僅查看函式的名稱

            函式與script差異:    1. 函式並不會以名子來調用script那樣被執行在另一個行程中,執行一個函式的語意比較像是登入系統時,.bash_profile檔所做的事或是像以source命令來調用任何script。
                                2. 函式與script同名時,函式具有優先執行的權利

            各種命令優先權:
                                1. 別名
                                2. function 以及 if 和for 之類的關鍵字
                                3. 函式
                                4. 內建命令,像是cd 和type
                                5. script和可執行的程式,shell會根據PATH環境變數裡所列舉的目錄來搜尋他們
            如果名稱相同,別名會比函式和script具有更高的執行優先權。可以使用command,builtin 和 enable等內建命令來改變他們優先執行順序。
           
            type name : 解釋bash命令方式
                        type -a name 查看name所有定義
                        type -p name 查看限制為可執行檔或shell script
                        type -P name 查看限制為可執行檔或shell script 即使-t選項回傳值不是file
                        type -f name 查看只支援關鍵字、檔案以及別名。
                        type -t name 只查看描述單字alas, keyword, function, builtin 或file
                        -t可以和其他選項一起使用

    2. shell變數
        可以使用$VAR 取得值
        可以透過export讓子行程知道
        2.1 位置參數
            唯讀不能指定新值
            1 2 3等等: 他們的值$1 $2 $3表示第一個到第三個輸入參數

            0 值$0 : 代表script file name

            * 和 @ : 這2個特殊變數包含了所有的位置參數(位置參數0除外),兩者之間的差異相當微妙但很重要,而且只有當他們被雙引號刮住時,才會凸顯此一差異。
                "$*" : 是一個包含所有位置參數的單一字串,並以環境變數IFS(internal field separator)中的第一個字符做為位置參數的分隔符;IFS的預設通常是一個空格、跳格或換行符號。
                "$@" : 相當於"$1" "$2" ..."$N" N代表參數數目相當於N個以雙引號刮住的字串,並以空格為分隔符

            #    : 存放位置參數的數目
            2.1.1 函式中的位置參數
            -----------------------------------
            |         ascript(script)            |
            |    -------------                    |
            |    |    $var1    |                    |   
            |    -------------                    |
            |    -------------                    |
            |    |    $0        |                    |
            |    -------------                    |
            |    -------------                    |
            |    |    $1        |                    |
            |    -------------                    |
            |    -------------                    |
            |    |    $2        |                    |
            |    -------------                    |
            |    ---------------------            |
            |    |  函式 afunc        |            |
            |    |    -------------    |            |
            |    |    |    $1        |    |            |
            |    |    -------------    |            |
            |    |    -------------    |            |
            |    |    |    $2        |    |            |
            |    |    -------------    |            |
            |    ---------------------            |
            -----------------------------------
            $var1 $0 在ascript(script)和函式afunc都看的到
            script的$1 $2 只有在script看的到
            函式的$1 $2 只有在函式看的到

        2.2 函式裡的區域變數
            local var    #設定為區域變數

        2.3 具引號的$@和$*
            為什麼"$*"中的元素要以IFS的第一個字符做為分隔符號,而不使用空格就好?這是為了讓你的輸出具有彈性。
            為什麼"$@"的行為就好像是N個被加上雙引號的字串?這是為了讓你能再以分開的值來使用他們。
        2.4 變數的另一種語法
            除了$varname 外,還有${varname} 這個更一般化之語法的簡單形式。
            為什麼會有兩種語法?
                1. 如果你的程式碼參用到九個以上的位置參數時你必須用${10}來表示第十個參數,不可以用$10
                2. 如果想要在變數後面加一個底線之類符號
    3. 字串算符
        字串算符能讓你作以下幾件特別的事:
            確定變數存在與否(亦既有被定義而且其值不是空的)
            為變數設定預設值
            捕捉因變數未被設定所導致的錯誤
            移除變數值中與樣式相符的部份
        3.1 字串算符的語法
            字串算符的語法,基本上就是將具運算能力的特殊字符擺在變數名稱與右括號之間,而算符所需要的任何引數則會擺在算符的右邊。
            ${varname:-word} :    若varname存在而且不是空的,則傳為它的值;否則傳回word。
                                目的:若此變數沒有被定義,則傳回一個預設值。
                                ex.:  若count沒有定義 ${count:-0}的求值結果為0

            ${varname:=word} :    若varname存在而且不是空的,則傳回他的值;否則就把他設成word,然後傳回它的值。位置參數和特殊參數不能以這種方式指定。
                                目的:若某個變數沒有被定義,則為他設定一個預設值。
                                ex.: 若count沒有定義 ${count:=0} 會把count設成0。

            ${varname:?message} :    若varname存在而且不是空,則傳回它的值;否則印出varname:message,並放棄現行的命令或命令稿 (只適用於以非互動方式操作的shell)。若省略message則會產生parameter null or net set
                                目的:捕捉因變數未定義所導致的錯誤。
                                ex.: 若count沒有定義 ${count:?"undedined!"}會顯示 count:undefined!

            ${varname:+word}    若varname存在而且不是空的,則傳回word;否則傳回空值(null)。
                                目的:測試某個變數存在與否。
                                ex.: 若count有定義 ${count:+1}會傳回1(代表此事為真)。

            ${varname:offset:length} :進行子字串的擴展(substring expansion)。它會傳回$varname中開始位置為offset,字符個數為length的子字串。
                                    $varname中第一個字符的位置編號為0。若省略length,這個子字串將會從offset開始,一直延續到$varname的末端。
                                    如果offset小於0,那麼位置會從$varname的末端開始算起。
                                    如果varname是@,哪麼length就是從參數offset開始算起之位置參數的數目。
                                    目的:傳回某個字串的一部分(子子串或切片)
                                    ex.若count被設成frogfootman,則${count:4}會傳回footman。而${count:4:4}會傳回foot。

        3.2 樣式以及樣式比對
            ${variable#pattern}        如果pattern與變數值的開頭相符就刪除相符的部分(取最短者),並傳回變數其餘的部份。
            ${variable##pattern}    如果pattern與變數值的開頭相符就刪除相符的部分(取最長者),並傳回變數其餘的部份。
            ${variable%pattern}        如果pattern與變數值的結尾相符就刪除相符的部分(取最短者),並傳回變數其餘的部份。
            ${variable%%pattern}    如果pattern與變數值的結尾相符就刪除相符的部分(取最長者),並傳回變數其餘的部份。

            ${varable/pattern/string}
            ${varable//pattern/string}    在variable中符合pattern的部份(取最常者)會被取代成string。
                                        如果是第一種形式,只有的一個相符的部份會被取代。
                                        如果是第二種形式,所有相符的部份都會被取代。
                                        如果pattern是以一個#開始的,它就必須比對變數的開頭。
                                        如果pattern是以一個%開始的,它就必須和變數的結尾進行比對。
                                        如果string是空的,符合的部份會被刪除。
                                        如果variable是@或*,則會依序對每個位置參數作此操作。
        3.3 長度算符
            ${#varname}        它會傳回字符串之變數值的長度。

        3.4 經延伸的pattern比對算符
            *(patternlist)     所指定的pattern出現零或多次,代表符。
            +(patternlist)     所指定的pattern出現一或多次,代表符。
            ?(patternlist)     所指定的pattern出現零或一次,代表符。
            @(patternlist)     所指定的pattern出現一次,代表符。
            !(patternlist)     相符於任何pattern,但所指定的樣式除外。
    4. 命令替換
        $(UNIX Command)
   
五. 流程控制
    1. if/else
        if condition
        then
            statements
        [elif condition
            ethen statements...]
        [else
            statements]
        fi

        1.1 結束狀態
            0 通常代表沒問題的結束狀態。 其他編號(1~255)通常代表錯誤。
            如果結束狀態=0, condition 會被判定為真; 若為其他值則判定為否。

            $?    最後一個執行之命令的狀態。
        1.2 return N
            return 只能用在函式和以source 執行的shell script。相對而言exit N 會結束整個shell script。
           
        1.3 合併結束命令
            statement1 && statement2 執行statement1,如果它的結束狀態是0(true),繼續執行statement2。
            statement1 || statement2 執行statement1,如果它的結束狀態不是0(true),繼續執行statement2。

        1.4 條件測試
            [...]
            [[...]] 如同[...]但不會對括符裡的單字進行單字分離和路徑名稱擴展的動作。
           
            1.4.1 字串比較
                字串比較算符
                算符        若...為真
                ==================================================================               
                str1=str2    str1與str2相符
                str1!=str2    str1與str2不相符
                str1<str2    str1小於str2
                str1>str2    str2大於str2
                -n str1        str1不是空的
                -z str1        str1是空的
           
            1.4.2 檔案屬性檢查
                檔案屬性算符
                算符        若...為真
                ==================================================================               
                -a file        file 存在
                -d file        file 存在,而且是一個目錄。
                -e file        file 存在;如同-a
                -f file        file 存在,而且是一個普通檔案(並非目錄或其他特殊檔)
                -r file        擁有file的讀取權
                -x file        擁有file的執行權,或目錄的搜尋權
                -N file        自從上次讀取後file已被修改過
                -O file        擁有file的所有權
                -G file        file的群組識別碼符合你的群組識別碼,或是你的群組識別碼中的一個(如果你同時隸屬於多個群組)
                file1 -nt file2    file1比file2還新
                file1 -ot file2    file1比file2還舊

                if [ condition ] && [ condition ]; then
                if command && [ condition ]; then

        1.5 整數條件句
            算術測試算符
            測試            比較
            =================================================================
            -lt                小於
            -le                小於或等於
            -eq                等於
            -ge                大於或等於
            -gt                大於
            -ne                不等於

    2. for
        for 迴圈可讓已以固定的次數<重複執行某個區段的程式碼
        語法:
            for name [in list ]
            do
                用來處理 $name 的述句
            done
        list是一份名單(如果省略 in list,這份名單會被預設為"$@")

沒有留言:

張貼留言