本文也即《Learning the bash Shell》3rd Edition的第四章Basic Shell Programming之讀書筆記之二,但我們將不限於此。
String操作
在下面的描述中,“:”是可以刪除的,存在是表示“存在但不允許為null”,不帶“:”表示“存在”,即允許為空白:
${
varname
:-
word
}
:如果varname存在並且不為null,返回varname的值,否則返回word。用於當某個變數不存在或沒定義時返回一個預設的值。如果為${
varname
-
word
}
,則當varname存在,可以為null,例如我們定義myparam=,返回varname的值,否則返回word。下面也可以刪除“:”,含義相同,不在複述。
${
varname
:=
word
}
:如果varname存在並且不為null,返回varname的值,否則向其賦值為word,並返回該值。用於對某個不存在或沒定義變數設定預設。對於位置參數是唯讀不能賦值。
${
varname
message
}
:如果varname存在並且不為null,返回varname的值,否則列印資訊varname:message,並abort指令碼,如果我們沒有設定message,將使用預設的“parameter null or not set”。用於檢查變數沒有定義的錯誤。
${
varname
:+
word
}
:如果varname存在並且不為null,返回word的值,否則返回null。用於檢測變數是否存在。
${
varname
:
offset
:
length
}
:擷取substring的操作。他返回從varname中從offset位置開始,長度為length的字串。第一個位置為0,如果不給出length或者無效(小於0),則返回offset之後全部的字元,如果是{@:offset:length},則返回指令碼參數從第offset個參數開始的總共length個參數。
下面給出一個例子來學習他們的用法。我們建立一個檔案,在裡面存貯一些條目,我們希望能對條目進行排序,從大到小,並輸出最前的N個條目。檔案例如子如下:
[wei@wei-desktop bash-learning]$ cat myinfo
5 Depeche Mode
2 Split Enz
3 Simple Minds
1 Vivaldi, Antonio
20 Hello, world
7 adsf,dafdsf
15 Hello, myfriend
我們建立我們的指令檔highest用作測試,內容如下:其他顏色字型表示說明,不作為檔案的一部分,我們用注釋的方式,也不影響檔案的執行
# ”#“開始表示注釋行,一個良好的變成習慣是檔案的開始給出檔案的資訊,以便閱讀
# highest [howmany]
# sort the entry inf on a descend order, and high line the top
# [hwomany] entry, default is 5
#
# 要求使用者給出參數<檔案名稱>,否則退出指令碼,要求使用者給出顯示的條目,否則使用預設值5
filename=${1? 'Used command ./test [entry_num]'}
howmany=${2:-5}
# header是用來表明輸出的時候顯示的某些資訊,如果這行我們注釋掉,將不顯示
header=set
#echo帶有兩個參數-n,表示顯示後不執行LINEFEED,即不換行。-e表示解析/n,不將其作為兩個字元,視為分行符號號。我們如果注釋掉header,則不會顯示任何內容。
echo -e -n ${header:+"num name/n"}
echo -e -n ${header:+"---- -----/n"}
#sort是個排序的命令,-r表示reverse的順序,即從大到小,-n表示將第一個參數視為數字,而不是character的方式。| 表示pipe輸出,head -N
表示顯示頭N行。
sort -nr $filename | head -$howmany
樣式匹配
Pattern可以包含wildcard,操作如下:
- ${variable
#pattern
}
:如果變數的開始匹配pattern,則去除最小匹配,返回後面的字元,如果不匹配,給出變數。
- ${variable
##pattern
}
:如果變數的開始匹配pattern,則去除最大匹配,返回後面的字元,如果不匹配,給出變數。
- ${variable
%pattern
}
:如果變數的最後匹配pattern,則去除最小
匹配,返回前面的字元,如果不匹配,給出變數。
- ${variable
%%pattern
}
:如果變數的最後匹配pattern,則去除最大匹配,返回前
面的字元,如果不匹配,給出變數。
- ${variable
/pattern/string
}
:將第一個匹配更換為string,如果string為null,則刪除。如果variable是@或者*,則根據命令所得的參數為單元來執行。
- ${variable
//pattern/string
}
:將所有匹配更換為string,如果string為null,則刪除。如果variable是@或者*,則根據命令所得的參數為單元來執行。
最大或者最小批評只有在含有萬用字元的情況下有區別,否是對於精確匹配都是無區別的。下面是例子。
[wei@wei-desktop bash-learning]$ echo $aa
abc.xyz.hello.world
[wei@wei-desktop bash-learning]$ echo ${aa#*.}
xyz.hello.world
[wei@wei-desktop bash-learning]$ echo ${aa##*.}
world
[wei@wei-desktop bash-learning]$ echo ${aa%.*}
abc.xyz.hello
[wei@wei-desktop bash-learning]$ echo ${aa%%.*}
abc
[wei@wei-desktop bash-learning]$ echo ${aa/./-}
abc-xyz.hello.world
[wei@wei-desktop bash-learning]$ echo ${aa//./-}
abc-xyz-hello-world
圖案匹配經常用於檔案名稱的處理,例如去除路徑名,擷取檔案尾碼或者首碼等等。
查看extglob的選項是否開啟:shopt | grep extglob,如果開啟,可以使用或擴充的樣式匹配。開啟檔案shopt -s exglob,關閉使用-u。可以用這些來替代萬用字元:
例子,echo ${aa//+(abc|hello)/ALICE}的值為ALICE.xyz.ALICE.world
長度操作
${#varname
}
,例如上面的例子中${#aa}為19。
command substutuion:使用命令的輸入作為賦值
可以通過command substitution
來設定參數的值。允許將命令的輸出作為變數的賦值。在makefile的編寫中,我們曾使用類似的方式即`pkg-config clutter-1.0 --libs`,這裡用``包含的內容就是命令執行的輸出結果。但是這種方式是為了和舊版本相容,可以使用$(UNIX command
)的方式。這種方式可以嵌套的,及裡面的UNIX command也可以是command substitution。但是使用``的方式無法實現嵌套,下面是一些例子:
- $(ls $(pwd)),給出目前的目錄的檔案。例如$(ls $HOME),給出使用者目錄~下面的檔案。
- 例如type -all -path command給出命令的路徑,如果我們需要仔細查看相關檔案屬性,可以使用ls -l $(type -all -path vi)。
- vi $(grep -l 'command substitution' ch*),表示編輯目前的目錄開ch大頭的含有'command substitution'內容的檔案,其中-來表示,只顯示目標檔案。
cut和awk的用法:擷取列資訊
這兩個適用於獲得列的方式,舊的BSD系統不提供cut,需要使用awk來替代。使用方式cut –fN –dC filename或者awk –FC '{print $N}' filename。其中N表示列出,C表示分割符號,預設為tab。如果我們使用空格,可以為’ ‘,如果使用|等或產生奇異的特殊符合用/|的方式。例如顯示使用者名稱cat /etc/passwd | cut –f1 –d:。對於命令在stdout的輸出,使用空格對其,例如who,我們可以使用參數-cX-Y的方式,表示顯示為開始的第X個字元到第Y個字元,X從1開始,如果沒有Y,表示一直顯示到最後。例如who | cut –c10-15
一個stack的小例子
下面我們給出一個FILO的stack例子,用來複習string的操作。
push_func()
{
#注意如果沒有給出func的參數,則在func中跳出,而不是終結整個指令碼
entry=${1:?"Please enter the entry as push_func param"}
#注意在bottow後面有一個空格,我們使用空格作為分割,這是為了pop最後一個entry用
mystack="$entry ${mystack:-bottow }"
echo "push $entry in stack : $mystack"
}
pop_func()
{
#刪除最top的entry
mystack=${mystack#*' '}
#擷取當前stack的top元素
。
entry=${mystack%% *}
echo "After pop, top entry is '$entry', stack is $mystack"
}
push_func one
push_func
push_func two
pop
pop
pop
相關連結:
我的Linux操作相關文章