bash 字符串處理

記錄,方便查找

from: http://www.chinaunix.net/jh/7/575412.html

[精華] bash 編程
http://www.chinaunix.net 作者:jiupima 發表於:2005-07-22 16:29:17


Bash 編程
一. Bash特殊字符
1. 通配符:
*:匹配任何字符串
?:匹配任何單個字符
集合運算符:用一些單個字、一個連續範圍或斷續的字符集合作爲通配符
[set]:用字符集合作通配符匹配單個字符,如:[aeiou],[a-o],[a-h, w-z]
[!set]:除了集合外的所有字符組成的集合作通配符
2. 花括號展開式(可以嵌套):
格式:[前導字符串]{字符串1[{嵌套字符串1…}] [, 字符傳2…]}[後繼字符串]
如:c{a{r, t, n}, b{r, t, n}}s 就等於 cars cats cans cbrs cbts cbns
3. 其它特殊字符:
< :輸入重定向
>; :輸出重定向(沒有文件則創建,有則覆蓋)
>;>; :輸出重定向(沒有則創建,有則追加到文件尾部)
( :子shell開始,子shell繼承父shell部分環境變量
) :子shell結束
{ :命令塊開始,由當前shell執行,保留所有環境變量
} :命令塊結束
| :管道
/ :引用後面的單個字符
‘ :強引用字符串,不解釋特殊字符
“ :弱引用字符串,解釋所有特殊字符
~ :根目錄
` :命令替換
; :命令分隔符(命令終止符),運行在一行裏執行多條命令
# :行註釋
$ :變量表達式
& :在後臺執行命令
* :字符串通配符
? :單個字符通配符
二. Bash變量
1. 自定義變量
用戶自定義的變量由字母、數字和下劃線組成,並且變量名的第一個字符不能爲數字,且變量名大小寫敏感。
varname=value 注意bash不能在等號兩側留空格
shell語言是非類型的解釋型語言,給一個變量賦值實際上就是定義了變量,而且可以賦不同類型的值。引用變量有兩種方式,$varname和${varname},爲防止變量在字符串中產生歧義建議使用第二種方式,引用未定義的變量其值爲空。
爲一個變量賦值一個串,需要用到引號,注意`、’、”的不同,``相當於$()
爲了使變量可以在其它進程中使用,需要將變量導出:export varname
2. 環境變量
可以用set命令給變量賦值或查看環境變量值,使用unset命令清除變量值,使用export導出變量將可以使其它進程訪問到該環境變量。
3. 位置變量
位 置變量對應於命令行參數,其中$0爲腳本名稱,$1爲第一個參數,依次類推,參數超過9個必須使用${}引用變量。shell保留這些變量,不允許用戶以 另外的方式定義它們,傳給腳本或函數的位置變量是局部和只讀的,而其餘變量爲全局的(可以用local關鍵字聲明爲局部)。
4. 其它變量
$? :保存前一個命令的返回碼
$- :在Shell啓動或使用set命令時提供選項
$$ :當前shell的進程號
$! :上一個子進程的進程號
$# :傳給腳本或函數的參數個數,即位置變量數減1,不含腳本名稱。
$* :傳給腳本或函數的參數組成的單個字符串,即除腳本名稱後從第一個參數開始的字符串,每個參數以$IFS分隔(一般內部域分隔符$IFS爲1空格)。形同”…”
$@ :傳給腳本或函數的參數列表,這些參數被表示爲多個字符串。形同”” “” “”…。$*和$@之間的不同方便使用兩種方法處理命令行參數,但是在打印時參數外觀沒有區別。
如: #vi posparm.sh
function cutparm
{echo –e “inside cntparm: $# parms: $*/n”}
cntparm “$*”
cntparm “$@”
#./posparm.sh abc bca cab
inside cntparm: 1 parms: abc bca cab
inside cntparm: 3 parms: abc bca cab
三. Bash操作符
1. 字符串操作符(替換操作符)
${var:-word} 如果var存在且不爲空,返回它的值,否則返回word
${var:=word} 如果var存在且不爲空,返回它的值,否則將word賦給var, 返回它的值
${var:+word} 如果var存在且不爲空,返回word,否則返回空
${var:?message} 如果var存在且不爲空,返回它的值,
否則顯示“bash2:$var:$message”,然後退出當前命令或腳本
${var:offset[]} 從offset位置開始返回var的一個長爲length的子串,
若沒有length,則默認到var串末尾
2. 模式匹配操作符
${var#pattern} 從var頭部開始,刪除和pattern匹配的最短模式串,然後返回 剩餘串
${var##pattern} 從var頭部開始,刪除和pattern匹配的最長模式串,然後返回 剩餘串,basename path=${path##*/}
${var%pattern} 從var尾部開始,刪除和pattern匹配的最短模式串,然後返回 剩餘串,dirname path=${path%/*}
${var%%pattern} 從var尾部開始,刪除和pattern匹配的最長模式串,然後返回 剩餘串
${var/pattern/string} 用string替換var中和pattern匹配的最長模式串
四. Shell中條件和test命令
Bash可以使用[ … ]結構或test命令測試複雜條件
格式:[ expression ] 或 test expression
返回一個代碼,表明條件爲真還是爲假,返回0爲真,否則爲假。
注:左括號後和右括號前空格是必須的語法要求
1. 文件測試操作符
-d file file存在並且是一個目錄
-e file file存在
-f file file存在並且是一個普通文件
-g file file存在並且是SGID(設置組ID)文件
-r file 對file有讀權限
-s file file存在並且不爲空
-u file file存在並且是SUID(設置用戶ID)文件
-w file 對file有寫權限
-x file 對file有執行權限,如果是目錄則有查找權限
-O file 擁有file
-G file 測試是否是file所屬組的一個成員
-L file file爲符號鏈接
file1 –nt file2 file1比file2新
file1 –ot file2 file1比file2舊
2. 字符串操作符
str1=str2 str1和str2匹配
str1!=str2 str1和str2不匹配
str1<str2 str1小於str2
str1>;str2 str1大於str2
-n str str的長度大於0(不爲空)
-z str str的長度爲0(空串)
3. 整數操作符
var1 –eq var2 var1等於var2
var1 –ne var2 var1不等於var2
var1 –ge var2 var1大於等於var2
var1 –gt var2 var1大於var2
var1 –le var2 var1小於等於var2
var1 –lt var2 var1小於var2
4. 邏輯操作符
!expr 對expr求反
expr1 && expr2 對expr1與expr2求邏輯與,當expr1爲假時不再執行expr2
expr1 || expr2 對expr1與expr2求邏輯或,當expr1爲真時不再執行expr2
注:另一種邏輯操作符 邏輯與expr1 –a expr2 邏輯或expr1 –o expr2
五. Shell流控制
1. 條件語句:if
if 條件 IFS=:
then for dir in $PATH
語句 do
[elif 條件 if [ -O dir ]; then
語句] echo –e “/tYou own $dir”
[else else
語句] echo –e “/tYou don’t own $dir”
fi fi
2. 確定性循環:for done
for value in list for docfile in /etc/* /usr/etc/*
do do
statements using $value cp $docfile ${docfile%.doc}.txt
done done
注:for var;… 相當於for var in “$@”;…
3. 不確定性循環:while和until
while 條件 until 條件
do do
語句 語句
done done

count=1 count=1
while [ -n “$*” ] until [ -z “$*” ]
do do
echo "parameter $count" echo "parameter $count"
shift shift
count='expr $count + 1' count='expr $count + 1'
done done
條件爲真執行循環體 條件爲假執行循環體
注:整數變量的定義與算法
declare –i idx 定義整數變量 使用$(())無需定義
idx=1
while [ $idx!=150 ]
do
cp somefile somefile.$idx
idx=$idx+1 整數算法 idx=$(( $idx+1 ))
done
另一種算法 echo $(( 100/3 )) 將加減乘除表達式放入$(())中
4. 選擇結構:case和select
case 表達式 in 表達式和模式依次比較,執行第一個匹配的模式
模式1) ;;使程序控制流跳到esac後執行,相當於break
語句;; 允許表達式和含有通配符的模式進行匹配
模式2)
語句;;
……
[*)
語句]
esac

select value [ in list ] 按list列表自動生成菜單
do 若沒有list則默認爲位置變量
statements using $value
done
如:IFS=: 設置域分隔符爲:號
PS3=”choice>;” 改變select默認提示符
clear
select dir in $PATH
do
if [ $dir ]; then
cnt=$(ls –Al $dir | wc -l)
echo “$cnt files in $dir”
else
echo “No such choice !”
fi
echo –e “/npress ENTER to continue, CTRL-C to quit”
read 使程序按回車繼續,ctrl+c退出
clear
done
5. 命令shift
將存放在位置變量中的命令行參數依次向左傳遞
shift n 命令行參數向左傳遞n個串
六. Shell函數
定義: function fname fname ()
{ {
commands commands
} }
調用:fname [ parm1 parm2 parm3 ... ]
說明: 函數在使用前定義,兩種定義功能相同
函數名和調用函數參數成爲函數的位置變量
函數中的變量應該使用local聲明爲局部變量
七. 輸入輸出
限於篇幅,這裏不討論所有輸入輸出操作符和功能
1.I/O重定向
< :輸入重定向
>; :輸出重定向(沒有文件則創建,有則覆蓋)
>;>; :輸出重定向(沒有則創建,有則追加到文件尾部)
<< :輸入重定向(here文檔)
格式: command << label
input…
label
說明: 使一個命令的輸入爲一段shell腳本(input…),直到標號(label)結束
如: cat < $HOME/.profile >; out
echo “add to file end !” >;>; $HOME/.profile
ftp:USER=anonymous
[email protected]
ftp –i –n << END -i:非交互模式 -n:關閉自動登錄
open ftp.163.com
user $USER $PASS
cd /pub
close
END END標記輸入結束
2.字符串I/O操作
字符串輸出:echo
命令選項: -e:啓動轉義序列 -n:取消輸出後換行
轉義序列: /a:Alt/Ctrl+G(bell) /b:退格Backspace/Ctrl+H
/c:取消輸出後換行 /f:Formfeed/Ctrl+J
/r:Return/Ctrl+M /v:Vertical tab
/n:八進制ASCII字符 //:單個/字符 /t:Tab製表符
字符串輸入:read
可以用於用戶交互輸入,也可以用來一次處理文本文件中的一行
命令選項: -a:將值讀入數組,數組下標從0開始
-e:使用GNU的readline庫進行讀入,允許bash的編輯功能
-p:在執行讀入前打印提示
如: IFS=:
read –p “start read from file . filename is : /c” filename
while read name pass uid gid gecos home shell < filename
do
echo –e “name : $name/npass : $pass/n”
done
說明:如果行的域數大於變量表的變量數,則後面的域全部追加給最後的變量
八. 命令行處理
命令行處理命令:getopts
有兩個參數,第一個爲字母和冒號組成的選項列表字符串,第二個爲一個變量名
選項列表字符串以冒號開頭的選項字母排列組成,如果一選項需要一個參數則該選項字母后跟一個冒號
getopts分解第一參數,依次將選項摘取出來賦給第二個參數變量
如果某選項有參數,則讀取參數到內置變量OPTARG中
內置變量OPTIND保存着將被處理的命令行參數(位置參數)的數值
選項列表處理完畢getopts返回1,否則返回0
如: while getopts “:xy:z:” opt
do
case $opt in
x) xopt=’-x set’ ;;
y) yopt=”-y set and called with $OPTARG” ;;
z) zopt=”-z set and called with $OPTARG” ;;
/?) echo ‘USAGE: getopts.sh [-x] [-y arg] [-z arg] file…’
exit 1
esac
done
shift ($OPTING-1) 將處理過的命令行參數移去
echo ${xopt: -‘did not use –x‘}
echo ${yopt: -‘did not use –y‘}
echo ${zopt: -‘did not use –z‘}

echo “Remaining command-line arguments are :”
for f in “$@”
do
echo –e “/t$f/n”
done
九. 進程和作業控制
信號處理命令:trap
格式:trap command sig1 sig2 …
trap可以識別30多種信號,如中斷(Ctrl+c)、掛起(Ctrl+z)等,可以使用kill -l查看信號清單
當腳本接受到信號sig1、sig2等,trap就執行命令command,command完成後腳本重新執行
信號可以通過名稱或數字來標識
作業控制命令:bg、fg
bg:顯示後臺進程,即用Ctrl+z掛起或‘命令 &’執行的進程
fg:將後臺進程轉到前臺執行
kill –9 %n:殺掉第n個後臺進程
附錄:
一. Bash支持的命令行參數
-a 將所有變量輸出 
-c "string"從string中讀取命令 
-e 使用非交互式模式 
-f 禁止shell文件名產生 
-h 定義 
-i 交互式模式 
-k 爲命令的執行設置選項 
-n 讀取命令但不執行 
-r 受限模式 
-s 命令從標準輸入讀取 
-t 執行一命令,然後退出shell 
-u 在替換時,使用未設置的變量將會出錯 
-v 顯示shell的輸入行 
-x 跟蹤模式,顯示執行的命令
許多模式可以組合起來用,使用set可以設置或取消shell的選項來改變shell環境。打開選項用"-",關閉選項用"+",若顯示Shell中已經設置的選項,執行: $echo $-
二. .profile中shell的環境變量意思如下: 
CDPATH 執行cd命令時使用的搜索路徑 
HOME 用戶的home目錄 
IFS 內部的域分割符,一般爲空格符、製表符、或換行符 
MAIL 指定特定文件(信箱)的路徑,有UNIX郵件系統使用 
PATH 尋找命令的搜索路徑(同dos的config.sys的 path) 
PS1 主命令提示符,默認是"$" 
PS2 從命令提示符,默認是">;" 
TERM 使用終端類型
================================================================================
from: http://unix-cd.com/unixcd12/article_view.asp?id=4440

到長度

%x="abcd"
#方法一
%expr length $x
4
# 方法二
%echo ${#x}
4
# 方法三
%expr "$x" : ".*"
4
# expr 的幫助
# STRING : REGEXP   anchored pattern match of REGEXP in STRING
查找子串

%expr index $x "b"
2
%expr index $x "a"
1
%expr index $x "b"
2
%expr index $x "c"
3
%expr index $x "d"
4
得到子字符串

# 方法一
# expr <string> startpos length
%expr substr "$x" 1 3
abc
%expr substr "$x" 1 5
abcd
%expr substr "$x" 2 5
bcd
# 方法二
# ${x:pos:lenght}
%echo ${x:1}
bcd
%echo ${x:2}
cd
%echo ${x:0}
abcd
%echo ${x:0:2}
ab
%pos=1
%len=2
%echo ${x:$pos:$len}
bc
匹配正則表達式

# 打印匹配長度
%expr match $x "."
1
%expr match $x "abc"
3
%expr match $x "bc"
0
字符串的掐頭去尾

%x=aabbaarealwwvvww
%echo "${x%w*w}"
aabbaarealwwvv
%echo "${x%%w*w}"
aabbaareal
%echo "${x##a*a}"
lwwvvww
%echo "${x#a*a}"
bbaarealwwvvww
其中 , # 表示掐頭, 因爲鍵盤上 # 在 $ 的左面。
其中 , % 表示%, 因爲鍵盤上 % 在 $ 的右面。
單個的表示最小匹配,雙個表示最大匹配。
也就是說,當匹配的有多種方案的時候,選擇匹配的最大長度還是最小長度。

字符串的替換

%x=abcdabcd
%echo ${x/a/b} # 只替換一個
bbcdabcd
%echo ${x//a/b} # 替換所有
bbcdbbcd
不可以使用 regexp , 只能用 * ? 的文件擴展方式。

發佈了62 篇原創文章 · 獲贊 0 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章