Linux 伺服器系統管理第十三章 Shell Script 程式設計  上一頁    下一頁

13-6 字串處理

內容:

字串處理在 Shell Script 裡算是比較複雜且重要的工具,有了這些工具才能顯現出它與一般程式語言不同的地方。這裡僅介紹一些入門觀念,如欲更深入地研究,可能須參考有關 Shell Perl 語言工具書籍。

13-6-1 字串串接處理

基本上,Shell 變數內都是以字串格式儲存,只不過當它被取出來使用時,才再決定要以何種資料型態處理。而字串的串接方法就顯得非常容易,只要將兩個變數排列一起,就是串接處理,操作範例如下:

$ name=Data           => 設定 name 變數內容為字串 Data

$ number=5           => 設定 number 變數內容為字串 5

$ fileName=$name$number  => fileName 內容為兩字串串接

$ echo $fileName          => 顯示 fileName 變數內容

Data5

(A) 範例 ex7_21

許多情況下,檔案名稱需要加入日期,才能顯現出該檔案所記錄資料的產生時間。命令 date 為顯示日期功能,可利用 %Y%m %d 表示所欲顯示的年、月與日的格式,因此我們可利用 `date +%Y_%m_%d`(為反向單引號)來擷取當天的年、月、日,操作範例如下:

[tsnien@Secure-1 ~]$ today=`date +%Y_%m_%d`

[tsnien@Secure-1 ~]$ echo $today

2009_07_21

假設我們需要每天記錄某些事件,檔案名稱最好與當天日期相吻合,則產生該檔案的程式如下$vi ex7_21

#! /bin/bash

# file name: ex7_21

mainName=secure                    => 設定 mainName 變數內容

today=`date +%Y_%m_%d`             => 設定 today 變數內容

fileName=$mainName$today            => 兩字串串接

touch $fileName                     => 利用 touch 產生空白檔案

執行結果如下:

[tsnien@Secure-1 ~]$ ex7_21

[tsnien@Secure-1 ~]$ ls |grep secure

secure2009_07_21             => 已產生名稱加日期的檔案名稱

(B) 範例 ex7_22

某些紀錄檔案並不需要日期,而是以週期性的序號標示,譬如由 secure0secure1…… secure 5,依序產生。當紀錄檔產生到 secure5 之後,下一個再由 secure0開始。我們需利用一個環境變數(Count),來紀錄目前所產生的序號。每次要產生記錄檔案之前,先測試該變數是否已超過 5,如到達 5,則由 0 再開始,否則累加 1。程式範例如下$vi ex7_22

# file name: ex7_22

mainName=secure

max=5

if test $Count -gt $max

   then

        Count=0

   else

        Count=`expr $Count + 1`

fi

fileName=$mainName$Count

if test -f $fileName

   then

       `rm $fileName`

fi

touch $fileName

執行此範例之前須產生一個環境變數 Count,並必須將它 export 成整體變數,才會有效,如下:

[tsnien@Secure-1 ~]$ export Count=0   => 產生並 export 變數 Count

[tsnien@Secure-1 ~]$ ex7_22             => 執行範例

[tsnien@Secure-1 ~]$ ls -1 |grep secure  => 檢視是否產生 secure1 檔案

-rwxrw-r-- 1 tsnien tsnien 244  7 21 11:34 make_secure

-rw-rw-r-- 1 tsnien tsnien   0  7 22 09:46 secure1

13-6-2 字串替換處理 – { : }

到目前為止,我們對環境變數應該有一點初步的認識,為何它是設定使用者環境的主要因素?這是因為規劃環境程式係利用 Shell Script 編寫而成(如第六章所介紹),當執行設定程式時,則須按照某些環境變數的內容來決定執行結果如何。這樣雖然方便,但所需的環境變數是否已產生,在執行程式之前我們可能一無所悉,如此可能會造成錯誤。因此,我們可能需要某些字串處理工具,基本上它包含下列功能:

ü  判斷變數是否存在(變數已被定義與空值並不相同)

ü  設定變數的預設值

ü  移除變數中某些式樣與相符部份

當然上述功能是相互混合的。譬如我們欲變更某一變數的內容時,須先測試該變數是否存在,存在與否處理的方式當然不同。字串處理的符號是兩左右大括號({…})包著變數名稱,外邊再用一個錢記號表示變數,如 ${….},括號內決定處理哪些事物。表 13-1 為字串替換處理符號。

13-1 字串替換處理符號

字串處理符號

            

${varName:-word}

varName 存在而且不是空值,則傳回該值,否則傳回 word。功能是測試某個變數是否被定義,若無則回傳預設值。

${varName:=word}

varName 存在而且不是空值,則傳回該值,否則將它設定為 word,並回傳。功能是測試某個變數是否被定義,若無則產生並設定初值 word

${varName:+word}

varName 存在而且不是空值,則傳回 word,否則傳回空值(null)。功能是測試某個變數是否存在。

${varName:?message}

varName 存在而且不是空值,則回傳該值,否則印出 varName message 訊息,並結束當時的 Shell 程式。功能是測試某個變數是否被定義,以免造成執行上錯誤。

${varName:offset}

${varName: offset:length}

傳回 $varName 變數內由 offset 位置開始(由 0 開始計算),共計 length 長度的字串。如無指定 length,則傳回 offset 位置以後的字元。功能是切割字串。譬如 count=1234567,則 ${count:3},則傳回 4567。如 ${count:3:2},則傳回 45

在表 13-1 中,每一個敘述句都包含冒號(如 ${varName:-word}),其實除了最後一個敘述句之外,冒號是可以省略的。如沒有冒號,則功能是將『若 varName 存在而且不是空值』改為『若 varName 存在』。譬如 ${varName=word},則表示『若 varName 存在,則傳回該值,否則設定成 word,並回傳』。

(A) 範例 ex7_23

13-3-1 節範例中,我們依據環境變數 Count 內容,來決定所欲產生的檔案名稱如何,如果 Count 變數不存在的話,可能會造成執行的錯誤。下一個範例是利用 ${Count:=1} 測試 Count 變數是否存在,如存在的話,則回傳該變數的內容,如不存在的話,則回傳空值。程式範例如下:$vi ex7_23

# file name: ex7_23

mainName=secure

max=5                          => 最高數值為 5

echo "Start Count = $Count"           => 顯示目前 Count 變數的內容

now=${Count:=1}                => 將測試 Count 變數的結果存入 now

if [ -n "$now" ]                  => 測試 now 變數內是否空值

   then                       => 如不是空值,則執行下列語句

       if [ $now -ge $max ]      => now 是否超過或等於 5

          then

              now=0

          else

              now=`expr $now + 1`   => now 變數累加一

       fi

       fileName=$mainName$now   => 製作檔案名稱,如 secure3

       if [ -f $fileName ]          => 該檔案存在則刪除

          then

              rm $fileName

       fi

       touch $fileName               => 產生新的檔案

   else

       echo "The Count variable is not Exist, no success"

fi

export Count=$now           => 將新的Count 內容輸出成環境變數

echo "Last Count = $Count"      => 顯示最後的 Count 內容

上述範例中比較特殊的地方。是測試某變數的內容是否是空值,它的語法是 [ -n “$now” ],利用雙引號包起來表示字串的意思,字串才可以判斷他的長度是否為 0,如果是 0 的話,則表示內容是空值。編輯完後,我們的執行結果如下:

[tsnien@Secure-1 ~]$ ex7_23       => 還未產生 Count 之前執行

Start Count =

The Count variable is not Exist, no success

Last Count =

[tsnien@Secure-1 ~]$ export Count=3   => 產生環境變數 Count

[tsnien@Secure-1 ~]$ ex7_23

Start Count = 3

Last Count = 4

[tsnien@Secure-1 ~]$ ls secure*

ecure4

13-6-3 字串比對處理 – { # }

將某變數(varName)的內容以字串格式觀察,與某一字串樣式(pattern)做比對,如變數內容的起頭(#)或結尾(%)相符,則刪除取回最短(#%)或最長部分(##%%)。另一種處理方式,是變數內容與樣式比對,變數內相同部份由另一個樣式替換(/)。表 13-2 為字串替換處理符號。

字串比對符號

            

${varName#pattern}

若變數(varName)內容的開頭與 pattern 相符,則刪除相符部分(取最短者),並傳回變數剩餘部份。

${varName##pattern}

若變數(varName)內容的開頭與 pattern 相符,則刪除相符部分(取最長者),並傳回變數剩餘部份。

${varName%pattern}

若變數(varName)內容的結尾與 pattern 相符,則刪除相符部分(取最短者),並傳回變數剩餘部份。

${varName%%pattern}

若變數(varName)內容的結尾與 pattern 相符,則刪除相符部分(取最長者),並傳回變數剩餘部份。

${varName/pattern /string}

${varName//pattern /string}

若變數(varName)內容的開頭與 pattern 相符(varName/),則由 string替換該相符部分。另一種是比對結尾部分(varName//),如果與 pattern 相符,則由 string 字串替換。

(A) 範例 ex7_24:測試樣式比對

由表 13-2 中也很難看出樣式比對的用法,我們利用一個很簡單的範例來驗證它。假設某一變數 Name=/first/second/third/full.file.name,我們製作一程式,分別擷取出:

ü  full.file.name##):由起頭開始比對與樣式相同最長者。

ü  second/third/full.file.name#):由起頭開始比對與樣式相同最短者。

ü  /first/second/third/full.file%):由結尾開始比對與樣式相同最短者。

ü  /first/second/third/full%%):由結尾開始比對與樣式相同最長者。

程式範例如下$vi ex7_24

#! /bin/bash

# file name: ex7_24

Name="/first/second/third/full.file.name"

echo "Original name => $Name"

name1=${Name##/*/}

echo "From head and match all => $name1"

name2=${Name#/*/}

echo "From head and match one => $name2"

name3=${Name%.*}

echo "From tail and match one => $name3"

name4=${Name%%.*}

echo "From tail and match all => $name4"

執行結果如下:

[tsnien@Secure-1 ~]$ ex7_24

Original name => /first/second/third/full.file.name

From head and match all => full.file.name

From head and match one => second/third/full.file.name

From tail and match one => /first/second/third/full.file

From tail and match all => /first/second/third/full

(B) 範例 ex7_25:變更 Windows 路徑表示

在許多情況下,我們常會利用網路將 Windows 系統下某一目錄掛於 Linux 系統,但 Windows 路徑表示的斜線與 Linux 相反,我們可以編寫一程式將 Windows 的反斜線變更為正斜線,並加入所掛載於系統目錄位置,程式範例如下$ vi ex7_25

#! /bin/bash

# file name: ex7_25

win="c:\windows\data\dir\file.type"

echo "Windows file name = $win"

name1=${win##[cC]:}                  => C c 磁碟機皆可

echo "Delete device name => $name1"

name2=${name1//'\'/'/'}

echo "Change slash => $name2"

net="/network"

name3=${net}$name2

echo "Mount to /netowrk => $name3"

執行結果如下:

[tsnien@Secure-1 ~]$ ex7_25

Windows file name = c:\windows\data\dir\file.type

Delete device name => \windows\data\dir\file.type

Change slash => /windows/data/dir/file.type

Mount to /netowrk => /network/windows/data/dir/file.type

(C) 範例ex7_26:變更 URL 成為檔案目錄位置

許多情況,我們必須將 URL 所表示轉換成檔案目錄表示法,程式範例如下$vi ex7_26

#! /bin/bash

# file name: ex7_26

url="Linux.mis.csu.edu.tw"

echo "URL => $url"

name1=${url//'.'/'/'}

echo "Change to file name => $name1"

執行結果如下:

[tsnien@Secure-1 ~]$  ex7_26

URL => Linux.mis.csu.edu.tw

Change to file name => Linux/mis/csu/edu/tw

 

翻轉工作室:粘添壽

 

Linux 伺服器系統管理 - CentOS:

 

 

 

翻轉電子書系列: