Bourne shell (/bin/sh) 存在于所有的 Unix 系統(tǒng)上,并且用她寫(xiě)的腳本是(完全)可移植的; man 1 sh
是一個(gè)好的參考。
使用 variable=value
的命令格式設(shè)置變量,其中 variable 是變量名稱,value是打算賦給該變量的值。使用 $variable 獲取變量值。
MESSAGE="Hello World" # 賦予一個(gè)字符串
PI=3.1415 # 賦予一個(gè)十進(jìn)制小數(shù)N=8
TWON=`expr $N * 2` # 算術(shù)表達(dá)式(只限整數(shù))
TWON=$(($N * 2)) # 另一種語(yǔ)法
TWOPI=`echo "$PI * 2" | bc -l` # 使用 bc 進(jìn)行浮點(diǎn)運(yùn)算
ZERO=`echo "c($PI/4)-sqrt(2)/2" | bc -l`
命令行參數(shù):
$0, $1, $2, ... # $0 命令本身
$# # 命令參數(shù)個(gè)數(shù)
$* # 所有參數(shù)(也可以是 $@)
$$ # 當(dāng)前進(jìn)程 ID
$? # 最后命令退出狀態(tài)碼
command if [ $? != 0 ]; then
echo "command failed" fimypath=`pwd`mypath=${mypath}/file.txt
echo ${mypath##*/} # 只顯示文件名
echo ${mypath%%.*} # 除了擴(kuò)展名的全路徑
var2=${var:=string} # 如果var沒(méi)有被賦值,則string值先賦值給var,
# 然后再賦值給var2
for file in `ls`
do
echo $file
done
count=0
while [ $count -lt 5 ]; do
echo $count
sleep 1
count=$(($count + 1))
done
myfunction() {
find . -type f -name "*.$1" -print # $1 為方法的第一個(gè)參數(shù)
}
myfunction "txt"
MYHOME=/home/colin
cat > testhome.sh << _EOF# 所有_EOF前的代碼都會(huì)進(jìn)入到 testhome.sh 文件中去
if [ -d "$MYHOME" ] ; then
echo $MYHOME exists
else
echo $MYHOME does not exist
fi
_EOF
sh testhome.sh
來(lái)一個(gè)小實(shí)例,此腳本從本 xhtml 文檔創(chuàng)建一個(gè) PDF 小冊(cè)子:
#!/bin/sh# 此腳本可以創(chuàng)建一份供雙面打印機(jī)打印的 PDF 格式的書(shū)
if [ $# -ne 1 ]; then # 檢查參數(shù)是否等于 1
echo 1>&2 "Usage: $0 HtmlFile"
exit 1 # 如果不等于1,非0退出
fi
file=$1 # 文件變量
fname=${file%.*} # 文件名變量
fext=${file#*.} # 文件擴(kuò)展名變量
prince $file -o $fname.pdf # www.princexml.com
pdftops -paper A4 -noshrink $fname.pdf $fname.ps # 創(chuàng)建 postscript 小冊(cè)子
cat $fname.ps |psbook|psnup -Pa4 -2 |pstops -b "2:0,1U(21cm,29.7cm)" > $fname.book.ps
ps2pdf13 -sPAPERSIZE=a4 -sAutoRotatePages=None $fname.book.ps $fname.book.pdf # 在 Windows 上使用 #a4 和 #None!
exit 0 # exit 0 意為成功
這里是單行 sed 命令的金礦。還有一個(gè)很好的 sed 介紹及教程。
sed 's/string1/string2/g' # 替換 string1 為 string2
sed -i 's/wroong/wrong/g' *.txt # 用 g 替換所有返回的單詞
sed 's/\(.*\)1/\12/g' # 修改 anystring1 為 anystring2
sed '/<p>/,/<\/p>/d' t.xhtml # 刪除以 <p> 開(kāi)始,以 </p> 結(jié)尾的行
sed '/ *#/d; /^ *$/d' # 刪除注釋和空行
sed 's/[ \t]*$//' # 刪除行尾空格 (使用 tab 代替 \t)
sed 's/^[ \t]*//;s/[ \t]*$//' # 刪除行頭尾空格
sed 's/[^*]/[&]/' # 括住首字符 [] top -> [t]op
sed = file | sed 'N;s/\n/\t/' > file.num # 為文件添加行號(hào)
一些基本的正則表達(dá)式同樣可用于 sed。作為一個(gè)良好的啟蒙,可看 基本正則語(yǔ)法。
[\^$.|?*+() # 特殊字符,其他字符將匹配自身
\ # 轉(zhuǎn)義特殊字符,當(dāng)成普通字符對(duì)待
* # 重復(fù)前項(xiàng) 0 次或多次
. # 單個(gè)字符除換行符
.* # 匹配 0 個(gè)或多個(gè)字符
^ # 匹配字符串行開(kāi)始處
$ # 匹配字符串行結(jié)尾處
.$ # 匹配字符串行最后一個(gè)字符
^ $ # 匹配單個(gè)空格的行
[^A-Z] # 匹配任何以 A-Z 字符開(kāi)始的行
下列命令對(duì)于包含于一個(gè)腳本或者單行命令來(lái)說(shuō)很有用。
sort -t. -k1,1n -k2,2n -k3,3n -k4,4n # 排序 IPv4 格式的 IP 地址
echo 'Test' | tr '[:lower:]' '[:upper:]' # 轉(zhuǎn)換成大寫(xiě)
echo foo.bar | cut -d . -f 1 # 返回 foo
PID=$(ps | grep script.sh | grep bin | awk '{print $1}') # 正在運(yùn)行名為 script 腳本的
PIDPID=$(ps axww | grep [p]ing | awk '{print $1}') # ping 的 PID (w/o grep pid)
IP=$(ifconfig $INTERFACE | sed '/.*inet addr:/!d;s///;s/ .*//') # Linux
IP=$(ifconfig $INTERFACE | sed '/.*inet /!d;s///;s/ .*//') # FreeBSD
if [ `diff file1 file2 | wc -l` != 0 ]; then [...] fi # 文件改變了?
cat /etc/master.passwd | grep -v root | grep -v \*: | awk -F":" \ # 創(chuàng)建 http passwd
'{ printf("%s:%s\n", $1, $2) }' > /usr/local/etc/apache2/passwd
testuser=$(cat /usr/local/etc/apache2/passwd | grep -v \ # 查看 passwd 中的用戶
root | grep -v \*: | awk -F":" '{ printf("%s\n", $1) }' | grep ^user$)
:(){ :|:& };: # bash fork 炸彈。會(huì)干掉你的機(jī)器
tail +2 file > file2 # 刪除文件的第一行
我使用一種小伎倆來(lái)一次更改許多文件的擴(kuò)展名。舉個(gè)例子,從 .cxx 到 .cpp。排除最后的 | sh
先測(cè)試一下。你同樣可以使用命令 rename
來(lái)做這些,如果安裝了的話?;蛘呤褂?bash 內(nèi)建命令。
# ls *.cxx | awk -F. '{print "mv "$0" "$1".cpp"}' | sh
# ls *.c | sed "s/.*/cp & &.$(date "+%Y%m%d")/" | sh # 如 拷貝 *.c 成 *.c.20080401
# rename .cxx .cpp *.cxx # 重命名所有 .cxx 成 .cpp
# for i in *.cxx; do mv $i ${i%%.cxx}.cpp; done # bash 內(nèi)建的
更多建議: