Linux Bash編程須要注意的幾個地方

平常開發基本都在linux環境下,bash命令用的很多,可是寫腳本的地方很少。真的寫起來,發現須要注意的語法、使用習慣的小問題仍是很多。linux

查了些資料,也結合本身工做中遇到的一些問題,列舉幾個須要注意的地方shell

1. 變量及賦值

用等號給變量賦值,=先後都不能有空格。bash

export能夠將其設爲環境變量,當前SHELL及子進程有效;父進程的自定義變量沒法在子進程中使用。測試

var=32
now=`date +%y%m%d%H`
cur_path=`dirname $0`
PATH=$PATH:/home/user/bin

declare -x var也可講變量設爲環境變量。變量賦值,默認是string類型,經過declare命令可改爲其餘類型,好比:spa

declare -i sum=12+34  #i = integer
declare -a ... #a = array
2. 重定向

重定向:將命令的結果輸出到文件,而不是標準輸出(屏幕)。
code

  > 寫入文件並覆蓋舊文件orm

  >> 加到文件的尾部,保留舊文件內容。three

3. 單引號/雙引號/反引號

單引號 '進程

            兩個單引號包圍起來的字符串就是普通的字符串,它將保留原始的字面意思。ip

雙引號"

            兩個雙引號包圍起來的字符串,部分特殊字符將起到它們的做用.

            這些特殊字符有: 美圓符$, 反斜槓\, 反引號',  感嘆號!.

反引號 `         

            兩個反引號包圍起來的字符串,將做爲命令來運行,
            執行的輸出結果做爲該反引號的內容,稱爲命令替換,

            它有另外一種更好的寫法: $(command)

tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
4. if 控制語句

if [ ... ] then

...

elif ... then

...

else

...

fi

用" [ ] "來表示條件測試。注意這裏的空格很重要!要確保方括號的空格。

[ -f "somefile" ]  :判斷是不是一個文件

[ -x "/bin/ls" ]    :判斷/bin/ls是否存在並有可執行權限

[ -n "$var" ]       :判斷$var變量是否有值

[ "$a" == "$b" ]   :判斷$a和$b是否相等

5. 循環控制

-eq 等於 
-ne 不等於 
-gt 大於 
-ge 大於等於 
-lt 小於 

-le 小於等於


6. 使用{}加強變量的功能

? : 變量未定義,則顯示提示語word,腳本執行結束;

- : 變量未定義, 則使用新值word; 不改變變量原來的狀態;

+: 變量定義, 則使用新值word; 不改變變量原來的狀態; 與?不一樣的是,腳本不會中止執行;

=: 變量未定義, 則使用新值word, 並定義到變量;


變量有未定義與空值之分,要同時對這兩種狀況都進行判斷,能夠在上面的方法中加入冒號: 增長功能:

例如:

$ # a is undefined
$ b=""
$ c="Z"
$ echo a=${a-1}, b=${b-2}, c=${c-3}
a=1, b=, c=Z
$ echo a=${a:-1}, b=${b:-2}, c=${c:-3}
a=1, b=2, c=Z
7. Bash中的特殊變量:位置變量等

位置變量:$1~$9, 表明傳入給執行腳本的參數,從1開始,最多能夠有9個。例如,下面的腳本根據輸入的名字實現重命名功能:

#!/bin/sh
# rename: - rename a file
# Usage: rename oldname newname
oldname=$1
newname=$2
mv ${oldname:?"missing"} ${newname:?"missing"}

若是傳入的參數超過9個,或者說想傳入任意數量的參數,能夠用shift命令,來移除傳入的參數,例如:

#!/bin/sh
arg1=$1;shift;
arg2=$1;shift;
arg3=$1;shift;
echo first three arguments are $arg1 $arg2 and $arg3
#!/bin/sh
arg1=$1
arg2=$2
arg3=$3;shift 3
echo first three arguments are $arg1 $arg2 and $arg3

$0 - 腳本名字

$* - 全部的位置參數

使用這個變量,一樣能夠操做超過10個的位置參數。例以下面這個腳本,能夠把任意多個的文件移動到一個文件夾下:

#!/bin/sh
# scriptname: moveto
# usage: 
#	moveto directory files.....
directory=${1:?"Missing"};shift
mv $* $directory

調用的方法:
./moveto.sh /mytmp *.txt

$@ - 全部的位置參數(參數可包含空格)

此變量與$*的基本功能相似,不一樣的地方是,@能夠處理包含空格的參數。空格能夠分隔輸入參數,若是輸入參數包含空格,$@能夠返回包含空格的參數,$*則不能。能夠參考下面的例子來理解:

首先有一個打印變量名的腳本EchoArgs

#!/bin/sh
# ================
# usage:
#       echoes arguments  
# ================

E="echo -n"
# echo the name of script
${E} $0:
# now echo each argument
${E} "'${1-"?"}'"
${E} "'${2-"?"}'"
${E} "'${3-"?"}'"
${E} "'${4-"?"}'"
${E} "'${5-"?"}'"
${E} "'${6-"?"}'"
${E} "'${7-"?"}'"
echo

再寫一個測試腳本TestEchoArgs.sh

#!/bin/sh
# ================
# usage:
#      test echoes arguments  
# ================
./EchoArgs $*
./EchoArgs $@
./EchoArgs "$*"
./EchoArgs "$@"

測試輸入結果,比較兩個命令的不一樣:

./TestEchoArgs.sh "a b c" 'd e' f g

輸出:
./EchoArgs:'a''b''c''d''e''f''g'
./EchoArgs:'a''b''c''d''e''f''g'
./EchoArgs:'a b c d e f g''?''?''?''?''?''?'
./EchoArgs:'a b c''d e''f''g''?''?''?'

分析:

./EchoArgs $*
./EchoArgs $@ 
前兩個沒放在""中,結果同樣,由於$*和$@的執行以後都是傳給EchoArgs由空格分隔的七個參數
./EchoArgs "$*"
因爲$*不能分辨有空格的參數,最後傳給EchoArgs的只有一個""的參數
./EchoArgs "$@"
$@在""中分辨出有四個參數,前兩個參數中有空格。

$# - 參數個數

shift $#能夠去掉全部的傳入參數。

$$ - 當前進程的ID

因爲進程的ID都是不一樣的,這個變量能夠用來命名惟一的臨時文件。例以下面這個腳本,返回行數:

#!/bin/sh
# ************************************** 
# usage:
#       count lines of input file/files  
# **************************************

tempfile=/tmp/$0.$$

for i in $@
do
	if [ -f $i ]; then
	cat $i >> $tempfile
	fi
done

echo `wc -l $tempfile` lines were found
/bin/rm $tempfile

另外一個用處是,能夠在其餘進程中經過$$來kill這個進程。例如:

echo $$ >/tmp/job.pid

kill -HUP `cat /tmp/job.pid`

$! - 後臺進程的PID

只有運行&命令的進程纔會改變$!.使用此命令能夠控制多個後臺運行的程序,好比:

#!/bin/sh
job1 &
pid=$!
job2 &
pid="$pid $!"
job3 &
pid="$pid $!"
trap "kill -15 $pid" 0 1 2 15
wait

$? - 錯誤狀態

返回前一個程序的退出狀態。



----------

未完,不定時更新...

Last updated - 2/23/2016

相關文章
相關標籤/搜索