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
某些紀錄檔案並不需要日期,而是以週期性的序號標示,譬如由
secure0、secure1……
到
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 |
|