總網頁瀏覽量

2012年7月9日 星期一

Linux shell script


設定變數值
LOCALTEST=”test”
輸出
echo $LOCALTEST

可用set查看目前的變量內容,退出後即清除變量內容

唯讀變量用readonly宣告,小心使用,因為不能修改與清除
readonly LOCALTEST


環境變量
$HOME/.bash_profile(/etc/profile)
使用export設置,而env可以查看環境變量內容
export 環境變量名稱=”環境變量內容

${Variable name:+value}
如果設置了此變量,則顯示其值,否則為空
${Variable name:?value}
如果未設置了此變量,則顯示用戶定義錯誤訊息
${Variable name:-value}
如果未設置了此變量,則顯示其值
${Variable name:=value}
如果未設置了此變量,則設置其值並顯示

unset可清除變數值,不是設為0或空,而是將變數從整個環境移除
$0 腳本名稱,$1第一個變數、$2第二個變數~$9第九個變數
PWD變量表示當前目錄
&*+^|等特殊符號可使用 \ 來隱藏其特殊意義,當做成一般字元處理


運算符號
~op1 op1中所有的二進制的1變為00變為1
op1 << op2 op1中的二進制向左移動op2位,忽略最左端移出的各位,最右端的各位補上0值,每移一位即乘2
op1 >> op2 op1中的二進制向右移動op2位,忽略最右端移出的各位,最左端的各位補上0值,每移一位即除2
op1 & op2 做位元and運算
op1 ^ op2 做位元xor 運算
op1 | op2做位元or 運算


EX:
echo $[ 2+8 ]  //10
echo $[ 2>>8 ]  //0
echo $[ 2<<4 ]  //32
echo $[ 2^4 ]  //6
echo $[ 2|4 ]  //6
echo $[ ~3 ]  //-4


邏輯運算
&&
||

賦值運算符
=+=-=*=/=%=&=^=|=<<=>>=

$[ ]用整數完成,可接受不同基數的數字,[ base#n ]
EX:
$[ 10#8 + 1] //9


echo
顯示文本行或變量或者把字串輸入到文件
-e 解析轉譯字元
-n 回車不換行

EX:
echo “Write data”>test.txt
echo –e “This echo’s 3 new lines\n\n\n”   #沒加-e就不會空3


wc
wc可統計指定文件中的字元數、字元數、行數

-c: 統計字元數
-l: 統計行數
-w: 統計字數



字符
顯示
\b
退格
\c
行尾不帶行結束符
\f
換頁
\n
換行
\r
回車
\t
制符表
\\
反斜槓字符
\0nnn
ASCII值為nnn的字符,其中nnn13位八進制


read
可以從鑑盤或文件的某一行文本中讀入訊息,並將其賦給一個變量

EX:
echo –n “Enter a number A”
read number1
echo –n “Enter a number B”
read number2

echo “Number A is ${number1}”
echo “Number B is ${number2}”



cat
顯示文件內容創建、文件
加參數 more 可一頁一頁顯示

EX:
cat myfile
cat myfile1 myfile2 > myfile
cat –v dos.txt     #-v可顯示控制符號
cat myfile | more



|
可以通過管道把一個命令的輸出傳給另一個命令作為輸入

EX:
ls –l|grep “myfile”
df –k|awk ‘{print $1}’|grep  -v “FIlesystem ”   #-v過濾掉不需要的部份



tee
把輸出的一個副本輸送到標準輸出,另一個副本拷貝到相應的文件中
tee –a files
看到輸出的同時,也將其存入一個文件,一般用於管道之後

EX:
who |tee –a who.out  #-a表示append在文件後,沒加-a會直接覆蓋



重定向相關
文件
文件描述符
輸入文件 標準輸入
0
輸出文件 標準輸出
1
錯誤輸出文件 標準錯誤
2

command > filename  把標準輸出重定向一個文件中
command 1 > filename  把標準輸出重定向一個文件中
command >> filename  把標準輸出重定向一個文件中(附加)
command > filename 2>&1  把標準輸出和標準錯誤一起重定向到一個文件中
command 2 > filename  把標準錯誤重定向一個文件中
command 2 >> filename  把標準錯誤重定向一個文件中(附加)
command >> filename 2>&1 把標準輸出和標準錯誤一起重定向到一個文件中(追加)
command <filename > filename2 filename文件作為標準輸入,以filename2文件作為標準輸出
command <filename filename文件作為標準輸入
command <delimiter 從標準輸入中讀入,直到遇到delimiter分界符
command <&m 把文件描述符m作為標準輸入
command >&m 把標準輸出重定向到文件描述符m
command <&- 關閉標準輸入


EX:
重定向標準輸出
cat file |sort 1>sort.out
cat file |sort > sort.out
pwd >> path.out
>nullfile.txt  #創建一個文件

重定向標準輸入
sort <file
sort <name.txt >name.out



exec命令
用來替代當前shell,換句話說並沒有啟動子shell 使用這一個命令時任何現有環境都將會被清除,並重新啟動一個shell
exec command
其中的command通常是一個shell腳本


EX:
exec 3<&0 0<name.txt   #打開文件描述符
read line1
read line2
exec 0<&3     #關閉文件描述符
echo $line1
echo $line2



控制結構
If 條件1
then
           命令1
elif 條件2
then
           命令2
else
           命令3
fi

EX:
if[ “10” –lt “12” ]
then
           echo “Yes, 10 is less than 12”
fi



條件式判斷
(expression)  expression is true
! expression  expression is false
expression1 -a expression2   and
expression1 -o expression2   or
[-n] string            the length of string is nonzero
-z string                 thelength of string is zero
string1 = string2             the strings are equal
string1 != string2           the strings are not equal
integer1 –eq integer2 integer1 is equal to integer2
interger1 –ge integer2  integer1 is greater than or equal to integer2
integer1 –gt integer2    integer1 is greater than integer2
integer1 –le integer2   integer1 is less than or equal to integer2
integer1 –lt integer2    integer1 is less than integer2
integer1 –ne integer2   integer1 is not equal to interger2

file1 –ef file2        File1 and FIle2 have the same device and inode numbers
File1 –nt File2 File1 is newer(modification date) than File2
File1 –ot File2 File1 is older than File2
-b File File exists and is block special
-c File File exists and is character special
-d File File exists and is a directory
-e File File exists
-f File File exists and is a regular file
-g File File exists and is owned by the effective group ID
-k File File exists and


eq 等於               例如: 4 -eq 4   如果相等則為真,返回0,之後執行then後語句,反之返回1
ne :   不等於             例如: 4 -eq 4
le  小於等於         例如: 3 -le  5
ge 大於等於          例如:    5 -ge $num
lt   小於              例如:  5 -lt   $num
gt  大於               例如: 5  -gt  $num

對於字串比較:
-z   :字串是否為空串       例如: [  -z  $str  ]        如果為空串,則為真,返回為0
-n   :字串是否為非空串     例如: [  -z  $str  ]  
=   2個字串是否相同      例如: [  $str1 -z  $str2 ]  
!=   : 2個字串是否不相同    例如: [  $str1 -z  $str2 ]     如果2個字串不同,則為真,返回0

對於文件的判斷:
-d  filename   :判斷檔是否為目錄      例如:[  -d   /etc/passwd ]     如果為目錄,則為真
-f  filename   :
判斷檔是否為檔      例如:[  -d   /etc/passwd ]
-r  filename   :
判斷檔是否為可讀      例如:[  -d   /etc/passwd ]
-x  filename   :
判斷檔是否為可執行    例如:[  -d   /etc/passwd ]
-w  filename   :
判斷檔是否為可寫      例如:[  -d   /etc/passwd ]
-L  filename   :
判斷檔是否為連結檔  例如:[  -d   /etc/passwd ]
-e  filename   :
判斷檔是否為存在      例如:[  -d   /etc/passwd ]

邏輯運算子:
-a  邏輯與   相當有and      例如:[  $a -gt 90   -a   $a -lt 100 ]
-o  : 
邏輯或   相當有or         例如:[  $a -gt 90   -a    $a -lt 100 ] 
邏輯非                    例如:[  ! " $ a -gt 90" ] 


EX:
echo –n “Enter your name”
read NAME
if[ “$NAME” == “” ];then
           echo “You did not enter any information”
else
           echo “Your Name is ${NAME}”
fi

EX:
if cp myfile.bak myfile; then
           echo “good copy”
else
           echo “`basename $0`: error could not copy the files” >&2
fi



case語句
case in
模式1)
           命令1
           ;;
模式2)
           命令2
           ;;
esac

EX:
echo –n “Enter a number from 1 to 3:”
read ANS
case $ANS in
1)
           echo “You select 1”
           ;;
2)
           echo “You select 2”
           ;;
3)
           echo “You select 3”
           ;;
*)
           echo “`basename $0`: This is not between 1 and 3” >&2
           exit;
           ;;
esac

case中可加入|,表示邏輯或
EX:
case “$hour” in
           0? |1[01])
                     echo “Good morming”;;
           1[2-7])
                     echo “Good afternoon”;;
           *)
                     echo “Good evening”;;
esac



for循環
for變量名 in 列表
do
           命令1
           命令2
done

EX:
for loop in 1 2 3 4 5
do
           echo $loop
done


EX:
$cat run
tbl $1| nroff –mm –Tlp| lp
可以通過tblnrofflp命令執行一個文件

EX:
$for file in memo1 memo2 memo3 memo4
do
           run $file
done

如果要執行一個文件,這些文件名寫在文件的filelist
files=$(cat filelist)

for file in $files
do
           run $file
done

EX:
for file in $^
do
           tbl $file| nroff –rom –Tlp| lp
done



until循環
until 條件
do
           命令1
           命令2
done


EX:
Part=”/backup”
LOOK_OUT=`df|grep “$Part” |awk `{print $5}` |sed ‘s/%//g’`
ehco $LOOK_OUT
until [“$LOOK_OUT” –gt “90”]
do
           echo “FIlesystem /backup is nearly full” |mail root
           LOOK_OUT=`df|grep “$Part” |awk `{print $5}` |sed ‘s/%//g’`
           sleep 3600
done

EX:
等待某人登入系統

if [ “$#” –ne 1 ]
then
           echo “Usage:mon user”
           exit 1
fi

until who | grep “^$user ” > /dev/null
do
           sleep 60
done

EX:
修改上例,改為登入後發送email通知

if [ “$1” = -m ]
then
           mailopt=TRUE
           shift
else
           mailopt=FALSE
fi

if[ “$#” –eq 0 –o “$#” –gt 1 ]
then
           echo “Usage:mon [-m] user”
           echo “ –m means to be informed by mail”
fi

user=$1

util who|grep “^$user”>/dev/null
do
           sleep 60
done

if [ “$mailopt” = FALSE ]
then
           echo “$user has logged on”
else
           echo “$user has logged on”| mail steve
fi

ps:顯示登入用戶
who am i| cut –c 1-8



while循環
while 命令
do
           命令1
命令2
done


EX:
while read LINE
do
           echo $LINE
done <name.txt

EX:
while true
do
cmd=$(getcmd)
if [ “%cmd” = quit ]
then
           break
else
           processcmd “%cmd”
fi


break: 退出循環
continue: 跳過循環
while迴圈通常與shift合用,用來處理下一個引數

EX:
while [ “$#” –ne 0 ]
do
           echo “$1”
           shift
done

$Prargs a b c
輸出為
a
b
c


補充:
$?變量
用來判斷命令是否執行成功
$ echo $?
成功傳回0,失敗傳回非0



正規表達式
字浮
意義
^
匹配行首
$
匹配行尾
*
匹配0個或多個此單字符
[]
表示一個單字符或是範圍
\
隱避一個字符的特殊函義
.
匹配任意單字符,不含空字符
pattern\{n\}
匹配pattern出現次數
pattern\{n,\}
次數至少為n
pattern\{n,m\}
次數在nm之間



. 句點匹配任何單個字符
EX: r. 表示匹配r後跟任一個字符的模式
EX:
$ ed info
248
1,$p  //顯示所有行
/ … /  //搜索前後都有空格的任意三個字符
/     //重覆上次搜索
1,$s/p.o/xxx/g  //把所有”p.o”替換為”xxx”


^符號,表示他跟行首匹配
$ed info
248
/^the/   //搜索以the開頭的行
1$s/^/>>/  //在每行開頭插入>>

$符號,表示他跟行尾匹配
EX:
\.$  匹配一行結束處的句點
^\.  匹配以句點開頭的行
1,$s/$/>>/  在每行末尾添加>>
1,$s/..$//   刪除每行最後兩個字符

[]匹配字符組
[tT]he 會匹配小寫t或大寫T後緊跟he
[123456789] 匹配0~9數字
[A-Za-z] 匹配所有字母
[^A-Z] 匹配除大寫字母以外的任何字元

*匹配零或若干個字符
EX:
X* 匹配0123…個大寫的X
1,$s/  */ /g  把多個空格替換成一個空格

XX* 指匹配至少一個連續的X
XXX* 指匹配至少二個連續的X

\{…\} 匹配精確數目的字符串
\{min,max\},其中min表示前導正規表達式重覆的最小次數,max表示最大次數
EX:
X\{1,10\}匹配110個連續的X
[A-Za-z]\{4,7\} 匹配47個字母的序列

如果大刮號中只有一個數字,\{10\}表示正規表達式的數目必須正好這個數字
[a-zA..Z]\{7\} 匹配正好7個字母
.\{10\} 匹配正好10個字符(不管甚麼字符)

1,$s/^.\{10\}// 刪除每行的開頭5個字符
1,$s/.\{10\}$// 刪除每行的結尾5個字符

如果大刮號中只有一個數字,後面緊跟一個逗號,表示匹配至少多少前導正規表達式
+\{5,\} 匹配至少5個連續的加號
1,$s/[a-z][A-Z]\{6,\}/X/g 把至少6個字母替換為X

\(…\)保存匹配的字符串
^\(.\)\1 匹配行首第一個字符並保存到暫存器1



cut 命令
從數據文件或命令的輸出中解析
cut –c5  把第5個字符析取出來
cut –c1,13,50 1,13,50字符析取出來
cut –c20-50  20~50字符析取出來
cut –c5- data 把每一行第5個字符到行尾析取出來

cut –ddchar –ffileds file
dchar是數據中分隔各字段的分隔符,fileds表示要從文件file中析取出來的字段
EX:
檔案內容為
root:*:0:0:The Super User:/:/usr/bin/ksh

$cut –d: -f1 /etc/passwd
輸出root
$cut –d: -f1,6 /etc/passwd
輸出 root:/

EX:
檔案內容為
Alice Chebba  979-351-5541
Kent Lakers              154-050-4521

$cut –f1 phonebook
輸出
Alice Chebba 
Kent Lakers



paste命令
cut命令相反,不是把行分隔開,而是把多行合在一起

EX:
檔案names內容為
Aaa
Bfd

檔案numbers內容為
(307) 555-2050
(201) 500-4815

$pastes names numbers
輸出
Aaa (307) 555-2050
Bfd (201) 500-4815

-d選項: 用來分隔各行的ㄧ個或多個字符
$paste –d’+’ names address numbers

-s選項: 告訴paste把同一份文件的行黏在一起,而不是從其他文件
$ls | paste –d’ ‘ –s  #ls的輸出黏貼成一行,用空格分隔



sed命令
用來編輯數據的程序,與ed不同
$sed ‘s/Unix/UNIX/’ 檔案名  #Unix替換為UNIX
$who | sed ‘s/ .*$//’ 把一個空格後值到行尾(.*$)的跟任意內容替換為空(//)



tr命令
用來轉換標準輸入的字符
$tr e x < intro #把所有字母e轉換為x
$cut –d: -f1,6 /etc/passwd | tr : ‘  ’   #把冒號轉換為空格
$tr ‘[a-z]’ ‘[A-Z]’ < intro   #把文件intro中的小寫字母轉換為大寫字母

-s選項: 將文件中重覆出現的字符替換掉
$tr –s ‘:’ ‘\11’ 將一個或多個連續的冒號,替換成一個制符表
-d選項: 將指定的字符刪除掉



sort命令
$sort 文件
-u選項: 在輸出結果,去除重覆的行
-r選項: 顛倒排序順序
-n選項: 表示把行中第一個字段當作數值來排序
+1n,可跳過第一個字段
-t選項: -t後的字符數當作分隔符
-o選項: 可直接覆蓋舊文件寫檔

EX:
$sort +2n –t: /etc/passwd #以冒號為分隔號,跳過前兩個字段



uniq命令
在文件中去除重覆的行
$uniq names

-d選項: 挑出重覆的部分

shift命令
把傳進來的引數左移,原來存在$2的內容賦予$1$3的內容賦予$2



find命令
查找具有某些特徵文件的命令
find path name –options [-print –exec -ok]
-print 將匹配的文件輸出到標準輸出
-exec 對匹配的文件執行該參數所給出的shell命令,相應命令形式為 ‘command’ {} \;

EX:
到子目錄查找
find  /  -name  “a.java” –depth -print

EX:
find . –type f –exec ls –l {} \;
find . –name “*.log” –mtime +5 –ok rm{}\;



grep命令
grep [選項] 基本正則表示式 文件
-i 不區分大小寫
-l 只輸出包含匹配字符文件名
-n 顯示行數
-v 不包含
-E 開啟延伸表示式(需要使用正規表達式時要加上!)

正則表達式
^  一行的行首
$  一行的行尾
.  任何單獨的字元
[ ]  方括號包含一些字元範圍,只要其中一個字元吻合即可,例如a-e,若是被排除的字元範圍可以加上^符號

EX:
grep data *   #當前目錄下搜尋data
grep “kent” *.txt
grep “2004:22:5[0-9]” *.txt
grep “^[^210]” *.txt  #表示開頭不為210的文件
grep “H*P” *.txt
grep “4\{2\}” *.txt
grep “4\{2,\}” *.txt
grep “4\{2,4\}” *.txt
grep “^$” *.txt     #表示空行
grep “\?” *.txt       #包含問號
grep “^d” *.txt      #
grep “^[^d]” *.txt
grep “” *.txt
grep “” *.txt

grep特殊表示
[[:upper:]]             =>      [A-Z]
[[:lower:]]              =>      [a-z]
[[:alnum:]]             =>      [0-9a-zA-Z] 字母和數字符號字元
[[:alpha:]]              =>      [a-zA-Z]
[[:ascii:]]                =>      ASCII控制字元
[[:blank:]]              =>      空格或tab
[[:space:]]              =>      空格或tab
[[:digit:]]                =>      [0-9]
[[:xdigit:]]                =>    十六進位數值
[[:punct:]]                =>   標點符號字元
[[:print:]]                =>     可印的字元
[[:graph:]]                =>   非控制和非空白字元

如果指定-E選項開啟延伸比對功能,在正規表示式之後,會新增一些控制字元,如果需要使用這些字元,在字元之前要加上一個\符號

?             =>    選擇性比對,但最多吻和一次
*            =>     吻合0次或多次
+            =>     吻合1次或多次
{n}        =>     吻合n次
{n, }      =>     吻合n次以上
{n, m}   =>     吻合n次到m次

EX:
$grep e$ word2.txt
搜尋以e結尾的行

EX:
$grep -E [a-z]\{10\} word2.txt
搜尋小寫單字,並且長度剛好為10個字元長




参數展開
temp=1
echo $temp  => 1
echo ${temp} => 1
可以輸出正確的值

但在迴圈中只可使用${temp}來表示

for i in 1 2
do
    echo $i
done
會輸出空白


for i in 1 2
do
    echo ${i}
done
這樣才會輸出正確的值

参數代換
${param : -default}   =>   如果param是null,就設定它的值
${#param}                 =>   取得param的長度
${param%word}       =>   從尾端開始,移除param中,吻合word的最短部分,並回覆剩餘的部分
${param%%word}   =>   從尾端開始,移除param中,吻合word的最長部分,並回覆剩餘的部分
${param#word}        =>   從頭端開始,移除param中,吻合word的最短部分,並回覆剩餘的部分
${param##word}     =>   從頭端開始,移除param中,吻合word的最長部分,並回覆剩餘的部分

EX:
#!/bin/bash
unset foo

echo ${foo:-bar}

foo=fud
echo ${foo:-bar}

foo=/usr/bin/X11/startx
echo ${foo#*/}
echo ${foo##*/}

bar=/usr/local/etc/local/networks
echo ${bar%local*}
echo ${bar%%local*}

exit 0

輸出
bar
fud
usr/bin/X11/startx
startx
/usr/local/etc/
/usr/

EX:
轉換大量檔案,利用cjpeg方法轉換.gif to .jpg

#!bin/bash
for image in *.gif
do
    cjpeg $image > ${image%%git}jpg
done




awk
awk ‘{print $0}’ score.txt |tee score.out   #輸出一整行域
awk –F : ‘{print $1”\t”$4}’ score.txt |tee score.out    #以冒號分割
awk `BEGIN {print “IP      Date\n----------”} {print $1”\t”$4} END {print “end-of-report”}` score.txt|more

特殊元字符
+?
~匹配
!~不匹配

cat score.txt |awk `$0 ~ /218.79.131.86/`|grep “php”|wc -1
awk ‘{if ($1 == “218.79.131.96“) print $0}’ score.txt



expr命令
x=`expr $x + 1` 等同於 x=$(expr $x + 1)

EX:
$ expr 1 + 2
3

$ expr 10 + 20 / 2
20

$ expr 10 \* 20
200

expr1 | expr2  =>  如果expr1為非零,結果就是expr1,否則為expr2
expr1 & expr2  => 如果expr1和expr2都為零,結果就為零,否則為expr1

新版的script,通常使用較有效率的 $(( ))


算數擴展
$((expression))

EX:
$ i=$((100*200/10))
$ j=$((i<1000))   #如果i<2000j=0否則j=1
$echo $i $j
2000 0



雙引號與單引號
EX:
$ X=*
echo $X
輸出會顯示當前目錄

$ echo ‘$X’
輸出$x
$echo “$X”
輸出 *



反引號: command
EX:
$ echo The date and time is: `date`
輸出 The date and time is: Wed Aug 28 14:28:43

$(…)結構: $(command)
$ echo The date and time is: $(date)
輸出 The date and time is: Wed Aug 28 14:28:43



$#變量: 表示命令行中所鍵入的參數個數
$*變量: 表示可以引用傳遞給程序的所有參數
$@變量: 前後需加雙引號,與$*類似,但是$@會把以單引號內的引數視為一個引數,$*會視為兩個引數
$$變量: 顯示當前進程的id號碼

EX:
$cat args2
echo $# arguments passed
echo they are :$*:

$args2 a b c
3 arguments passed
they are :a b c:


$*與$@
$*: 所有參數的串列,以IFS變數的第一個字元作區隔。如果IFS變數內容改變,$*中區隔參數的方法,就會改變。$@為$*的變形,它不使用IFS變數,將所有變數以空白分隔,並存入$@。

EX:
$ IFS=''
$ set foo bar bam
$ echo "$@"   ==> foo bar bam
$ echo "$*"    ==> foobarbam
$ unset IFS
$ echo "$*"   ==>  foo bar bam



nl命令
添加行號列印

EX:
使用shell來達成

lineno=1
cat $* |
while read line
do
           echo “$lineno: $line”
           lineno=$((lineno + 1))
done



test命令
經常用來在if 命令測試一種或幾種條件
EX:
if test “$name” = Julio
then
           echo “Julio”
fi
#檢測test的退出狀態,如果為0,就執行thenfi之間的命令,如果不為0,就跳過echo

-n: 檢測參數長度是否不為0,如果不為0則返回的退出狀態為0
-s: 檢測參數長度是否為0,如果為0則返回的退出狀態為0

test的另一種格式,[ expression ]
EX:
if [“$name” = Julio ]
then
           echo “Julio”
fi


命令
返回真(退出狀態0)的條件

int1 –eq int2
等於
equal
int1 –ge int2
大於等於
greater equal
int1 –gt int2
大於
greater than
int1 –le int2
小於等於
less equal
int1 –lt int2
小於
less than
int1 –ne int2
不等於
non-equal


命令
返回真(退出狀態0)的條件

-d file
file為目錄

-e file
file存在
exist
-f file
file為普通文件
file
-r file
file為進程可讀文件
read
-s file
file長度不為0
size
-w file
file為進程可寫文件
write
-x file
file可執行
excute
-L file
file為符號化鏈結
link

邏輯運算與操作
-a: 兩個表達式皆為真則返回真
-o: 兩個表達式有一個為真則返回真

EX:
[ -f “$mailfile” –a -r “$mailefile” ]
[ -n “$count” –o –r $HOME/mailfile ]

 可用小括號控制優先權
[ \( “count” –ge 0 \) –a \( “$count” –lt 10\) ]


exit命令
終止shell執行


綜合範例
if [ $“matches” –gt 1 ]
then
           echo “符合大於1”
elif [ “$matches” –eq 1 ]
then
           grep –v “$name” phonebook > /temp/phonebook
           mv /tmp/phonebook
else
           echo “找不到$name”
fi



Debug使用
sh –x 程序名 參數
讓執行每條命令時,都會在終端上顯示出來

ps: wc –c 如果輸入參數為 a加回車時,wc2,因為自動加入enter



空命令
:
什麼也不做




&&||
根據前一個命令的成敗來決定後一個命令,格式 command1 && command2

command1 && command2
先執行command1,如果返回的退出狀態為0則執行command2,如果不為0,則跳過command2
命令從左邊開始執行,如果回覆為true,才會再執行下一個(右邊)命令

command1 || command2
先執行command1,如果返回的退出狀態不為0則執行command2,如果為0,則跳過command2
執行一連串命令,當其中有一個為true,則會跳出,不再執行

EX:
if sort bigdata > /tmp/sortout && mv  /sortout  bigdata

等價於
if sort bigdata > /tmp/sortout
then
           mv /tmp/sortout  bigdata
fi

結和這兩種方式
[ -f file ] && command for true || command for false
如果第一項檢查成功,才會執行第一個命令,檢查失敗會執行第二個命令


if [ "1" = "1" ] && echo "A" || echo "B"
then
        echo "Function1"
fi

if [ "1" = "2" ] && echo "C" || echo "D"
then
        echo "Function2"
fi

輸出:
A
Function1
B
Function2



sed命令
操作的只是拷貝一個文件,然後所有的改動將輸出到螢幕
sed [選項] sed命令 輸入文件
sed [選項] –f sed腳本文件 輸入文件
sed 腳本文件 [選項] 輸入文件
-n 不打印
-c 下一命令是編輯命令
-f 如果正在調用sed腳本文件


x
為一行號
x, y
表示行號範圍從xy
/pattern/
查詢包含模式的行
/pattern/pattern/
查詢包含兩個模式的行
pattern/,x
在給定行號上查詢包含模式的行
x,/pattern/
通過行號和模式查詢匹配行
x,y!
查詢不包含指定行號xy的行
基本sed編輯命令

p
打印匹配行
=
顯示文件行號
a\
在定位行號後附加新文本訊息
i\
在定位行號後插入新文本訊息
d
刪除定位行
c\
用新文本替換定位文本
s
使用替換模式替換相應模式
r
從另一個文件中讀文本
w
寫文本到一個文件
q
第一個模式匹配完成後退出
l
顯示八進制ascii等價的控制字符
{}
在定位行執行的命令組
n
從另一個文件中讀文本下一行,並附加在下一行
g
將模式2黏貼到/pattern n/
y
傳送字符

sed –n ‘2p’ score.txt  #印出第二行
sed –n ‘1, 4p’ score.txt  #印出第1~4
sed –n ‘/los/p’ myfile.txt
sed –n ‘/4,los/p’ myfile.txt



getopts命令
格式: getopts mt: option
getopts命令的設計目標是在循環中運行,每次執行循環,getopts就檢查下一個命令行參數,並判斷它是否合法


printf命令
不支援浮點數,因為shell只支援整數運算
格式:  printf “format” arg1 arg2

EX:
$printf “This is a number: %d\n” 10

EX:
$ printf "%s\n" hello
hello
$ printf "%s %d\t%s" "Hi There" 15 people
Hi There 15    people


字符
顯示作用
d
整數
u
無符號整數
o
八進制整數
x
a-f 十六進制
X
A-F 十六進制
c
字元
s
字串
b
包函反斜槓轉譯符的字串
%
百分號

-使顯示的值向左對齊
+顯示正負號
%#x%#X表示的十六進制整數前加前導符號0x0X
widthprecisionex: 10.5表示寬度為10位,數字顯示5


(…){…;}結構
EX:
$x=50
$(x=100)   #在子shell中執行
$echo $x
50
${x=100;}   #在當前shell中執行
$ehco $x
100

${parameter:-value}
如果parameter為空,就替換它的值,反之不為空時,shell就使用它的值

${parameter:=value}
parameter為空時,不但使用value,還把它賦予parameter

${parameter:?value}
如果parameter不為空,shell就替換它的值,否則shell就把value寫入標準錯誤,然後退出

${parameter:+value}
如果parameter不為空,則替換為value


模式匹配結構
${variable%pattern}
從右邊去掉最短匹配模式
${variable%%pattern}
從右邊去掉最長匹配模式
${variable#pattern}
從左邊去掉最短匹配模式
${variable##pattern}
從左邊去掉最長匹配模式

可搭配匹配字符
*: 匹配0或任意字符
?: 匹配一個任意字符
[…]: 匹配給定字符組中的ㄧ個字符
[!...]: 不匹配給定字符組中的任ㄧ個字符

EX: 查詢是否有.o檔文件
if [ ${file%.o} != $file ]
then
           …
fi

EX: 產生最右邊名稱
$cat mybasename
echo ${##*/} 

$mybasename /user/spool/uucppublic
輸出uucppublic



set命令
設置各種shell選項,以及給位置參數$1$2等重新賦值,對於一些命令,它的輸出文字是以空白區隔,若只要使用其中的ㄧ些欄位,這個命令就非常有用

set –xctype程序作用一樣,會開始顯示每一行命令追蹤
set -o xtrace會開啟追蹤
set +o xtrace會關閉追蹤

--選項,它讓set不要把行中後面的其他字符作為選項

$ echo the date is $(date)
$ set $(date)
$ echo The month is $2

the date is Wed Nov 7 22:05:14 EST 2012
The month is Nov



eval命令
eval command-line
shell在執行命令行之前掃瞄他兩次

EX:
$cat last
eval echo \$$#

$last one two three four
輸出four

因為掃描兩次,第一次後變為 echo \$4,第二次後即為取出第四個參數



wait命令
有時候希望等到後台進程完成後在繼續執行,就使得wait
格式: wait process-id
process-id為當前的進程標識符
$!變量:
如果後台只有一個進程在運行,wait命令就不需帶任何參數,如果有多個時,就可以使用$!

EX:
prog1 &
pid1=$!
prog2 &
pid2=$!
wait &pid1  #等待prog1完成
wait &pid2  #等待prog2完成



trap命令
當程式被中止時(ctrl + c),可能會留一些暫存文件,可以使用trap來協助刪除
trap command signals


EX:
trap “rm $WORKDIR/work$$ $WORKDIR/dataout$$; exit” 2
trap收到signal 2後會自動刪除work$$dataout$$文件


trap命令用來指定信號(signal)發生之後的行動,新的script可以#include signal.h,直接利用該檔案裡面定義的名稱。
重新設定trap回到預設狀態,只要簡單執行命令"trap -"即可

EX:
trap 'rm -f /tmp/my_tmp_file+$$' INT
當user按下Ctrl + c(或任何中斷鍵)就會執行這個動作

文件重定向
文件描述符0表示標準輸入
文件描述符1表示標準輸出
文件描述符2表示標準錯誤

EX:
command 2> file
command >& 2

把標準輸出和標準輸入都指向同一個文件
command >foo 2>>foo
or
command >foo 2>&1




信號
說明
HUP(1)
Hang up:當一個終端機斷線之後或使用者登出之後,通常會送出這信號
INT(2)
Interrupt:通常是按下Ctrl + C
QUIT(3)
Quit:通常是按下Ctrl + \
ABRT(6)
Abort: 通常有些嚴重的執行錯誤發生時,就會送出
ALRM(14)
Alarm: 通常用來處理逾時
TERM(15)
Terminate: 當系統要關機時,就會送出

函數:
格式 name() { command; … command;}

EX:
nu() { who | wc –l; }
輸入nu來執行



return命令
用來結束函數運行而不結束程序


type命令
用來查詢指令是屬於哪一種

命令歷史紀錄表
.bash_history

陣列
$arr[0]=hello
$arr[1]=”some.txt”
$arr[2]=.user/steve/memos

$echo ${arr[0]}
hello
$echo ${arr[1]}
some txt
$echo ${arr[2]}
.user/steve/memos

[*]:用來在命令行代替陣列的所有元素

EX:
$echo ${array[*]}
hello some.txt /user/steve/memos

{#array[*]}: 用來表示陣列中的元素個數


停止
使用ctrl + z停止任務後,如果要繼續任務,可使用bgfg繼續