2011-04-23 wcdj
學習shell程式設計的方法就是:動手 + man command
下面指令碼全部是在Cygwin下測試的。
$ /bin/bash --version
GNU bash, version 2.05b.0(1)-release (i686-pc-cygwin)
Copyright (C) 2002 Free Software Foundation, Inc.
編寫shell指令碼程式有兩種方式
:
【1】可以輸入一系列命令讓shell互動地執行它們。
【2】可以把這些命令儲存到一個檔案中,然後將該檔案作為一個程式來調用。
Bash常用命令
目錄
:
(1) read命令 —— 變數內容由使用者決定
(2) 重新導向輸出和輸入
(3) 管道 |
(4) find命令 —— 在系統中,搜尋檔案
(5) grep命令 —— 在檔案中,搜尋字串
(6) -exec 和 -ok 命令
(7) 算術擴充
(8) 參數擴充
(9) 指令碼的追蹤與調試
(1) read命令 —— 變數內容由使用者決定
例子
:
#! /bin/bash
# program:
# This program is used to show the usage of [read] command.
# History:
# 2011/04/23 wcdj First release
echo -e "This program is used to show the usage of [read] command."
read -p "Please input your first name: " firstname
read -p "Please input your last name: " lastname
echo -e "/nYour full name is: $firstname $lastname"
(2) 重新導向輸出和輸入
重新導向輸出 > 和 >>
檔案描述符0:代表一個程式的標準輸入
檔案描述符1:代表一個程式的標準輸出
檔案描述符2:代表一個程式的標準錯誤輸出。
重新導向輸入 <
(3) 管道 |
可以使用管道操作符 | 來串連進程。Linux與MS-DOS不同,在Linux下通過管道串連的進程可以同時運行,並且隨著資料流在它們之間的傳遞可以自動地進行協調。
例子1
:使用sort命令對ps命令的輸出進行排序。
ps | sort > pssort.out # 方法1:將結果儲存到pssort.out檔案中
ps | sort | more # 方法2:在螢幕上分頁顯示輸出結果
例子2
:查看系統中啟動並執行所有進程的名字,但不包括shell本身
ps -xo comm | sort | uniq | grep -v sh | more
Cygwin下ps沒有 -xo 選項。
注意
:
(1) 允許串連的進程數目是沒有限制的。
(2) 如果有一系列命令需要執行,相應的輸出檔案是在這一組命令被建立的同時立刻被建立或寫入的,所以決不要在命令流中重複使用相同的檔案名稱。比如下面這條命令:
cat mydata.txt | sort | uniq > mydata.txt
錯誤:最終將得到一個空檔案,因為在讀取檔案mydata.txt之前就已經覆蓋了這個檔案的內容。
(4) find命令 —— 在系統中,搜尋檔案
find命令的完整文法格式如下:
find [path] [options] [tests] [actions]
例子1
:在本地機器上尋找名為test的檔案,為了確保具有搜尋整個機器的許可權,請以root使用者身份來執行這個命令。
# find /home/wcdj -name test -print
輸出結果:
/home/wcdj/linux/openssl-SNAP-20091203/demos/tunala/test.sh
/home/wcdj/bash/test.sh
執行後,硬碟會瘋狂的轉動,需要花費很長的時間。
例子2
:在目前的目錄中搜尋比檔案file要新的檔案,如果這個測試通過,然後再測試這個檔案是否是一個普通檔案,最後,確認搜尋到的檔案。
find . /( -name "*" -or -newer file /) -type f -print
注意
:
(1) 使用圓括弧來強制測試和操作符的優先順序,由於圓括弧對shell來說有其特殊的含義,所以還必須使用反斜線來引用圓括弧。
(2) -name pattern 檔案名稱(不包括路徑名)匹配提供的模式pattern,為了確保pattern被傳遞給find命令而不是由shell來處理,pattern必須總是用引號括起。
(5) grep命令 —— 在檔案中,搜尋字串
grep命令的完整文法格式如下:
grep [options] PATTERN [FILES]
例子1
:從大量C語言源檔案中尋找包含字串POSIX的檔案,並輸出合格檔案名稱。
$ more `grep -l POSIX *` # 方法1:使用反引號
$ more $(grep -l POSIX *) # 方法2:使用$(...)擷取子進程的輸出
$ grep -l POSIX * | more # 方法3:使用管道 |
$ grep -l POSIX * -exec more {} /; # 方法4:使用-exec(可以顯示但會輸出一些錯誤)
例子2
:
grep wcdj words.txt # 在words.txt檔案中搜尋字串wcdj,然後輸出匹配的行
grep -c wcdj words.txt words2.txt # 在兩個不同的檔案中計算匹配行的數目。在這種情況下,檔案名稱被輸出
grep -c -v wcdj words.txt words2.txt # 使用-v選項對搜尋取反,在兩個檔案中計算不匹配行的數目
例子3
:使用Regex,實現更複雜的匹配
# [1] 尋找以字母e結尾的行
grep e$ words.txt
# [2] 尋找以字母a結尾的單詞
grep a[[:blank:]] words.txt
# [3] 尋找以Th開頭的3個字母組成的單詞
grep Th.[[:blank:]] words.txt
# [4] 使用擴充grep模式來搜尋只有10個字元長的全部由小寫字母組成的單詞
grep -E [a-z]/{10/} words.txt
(6) -exec 和 -ok 命令
-exec 和 -ok 命令將命令列上後續的參數作為它們參數的一部分,直到被 /; 序列終止。實際上,-exec 和 -ok 命令執行的是一個嵌入式命令,所以嵌入式命令必須以一個轉義的分號結束,使得find命令可以決定什麼時候它可以繼續尋找用於它自己的命令列選項。魔術字串{}是-exec或-ok命令的一個特殊類型的參數,它將被當前檔案的完整路徑取代。
例子
:
find . -name file -type f -exec ls -l {} /;
find . -newer file -type f -exec ls -l {} /;
(7) 算術擴充
expr命令可以處理一些簡單的算術命令,但這個命令執行起來相當慢,因為它需要調用一個新的shell來處理expr命令。
一種更新更好的辦法是使用$((...))擴充計算運算式的值。
注意
:
$((...))與$(...)不同,兩對圓括弧用於算術替換,而一對圓括弧用於命令的執行和擷取輸出。
例子
:列印輸出0~9
#! /bin/bash
# program:
# $((...))
# History:
# 2011/04/23 wcdj First release
x=0;
while [ "$x" -ne 10 ]
do
echo $x
x=$(($x+1)) # x=$(expr $x+1)
done
exit 0
(8) 參數擴充
將變數放在花括弧{}中,實現把參數的值替換進一個字串裡。
例子1
:
#! /bin/bash
# program:
# 參數擴充
# History:
# 2011/04/23 wcdj First release
for i in 1 2
do
echo ${i}_tmp
done
例子2
:使用cjpeg程式將目前的目錄中的每一個的GIF檔案建立一個對應的JPGE檔案
#! /bin/bash
# program:
# 參數擴充
# History:
# 2011/04/23 wcdj First release
for image in *.gif
do
cjpeg $image > $(image%%gif)jpg
done
注意
:
關於參數擴充的使用方法很多,更多使用方法見參考文獻[2]中P.60。
(9) 指令碼的追蹤與調試
sh -[nvx] scripts.sh
參數的意義:
-n:不要執行指令碼,僅查詢文法問題,若沒有文法問題,則不會顯示任何資訊
-v:在執行指令碼前,先將指令碼的內容輸出到螢幕上
-x:將使用的指令碼內容顯示到螢幕上,這是很有用的參數。使用 -x 是追蹤指令碼的好方法,它可以在執行前列出所有執行的程式段,如果是程式段落,則輸出時,最前面會加上 + 符號,表示它是程式碼,實際的輸出則與標準輸出有關。
例子
:下面這個指令檔的名字為test.sh
#! /bin/bash
# program:
# 參數擴充
# History:
# 2011/04/23 wcdj First release
for i in 1 2
do
echo ${i}_tmp
done
調試這個指令碼:
sh -x test.sh
顯示如下內容:
+ echo 1_tmp
1_tmp
+ echo 2_tmp
2_tmp
待續……
參考
:
[1] Linux鳥哥的私房菜基礎學習篇(第二版)
[2] Linux程式設計(第4版)