簡介
Shell是一種腳本語言,那么,就必須有解釋器來執行這些腳本。
Unix/Linux上常見的Shell腳本解釋器有bash、sh、csh、ksh等,習慣上把它們稱作一種Shell。我們常說有多少種Shell,其實說的是Shell腳本解釋器。
Hello World
打開文本編輯器,新建一個文件test.sh
,擴展名為.sh
(sh代表shell)。
輸入一些代碼:
#!/bin/bash
echo "Hello World !"
在命令行運行:
chmod +x test.sh
./test.sh
運行結果:
Hello World !
#!
是一個約定的標記,它告訴系統這個腳本需要什么解釋器來執行,即使用哪一種Shell。echo
命令用於向窗口輸出文本。
注釋
以#
開頭的行就是注釋,會被解釋器忽略。sh里沒有多行注釋,只能每一行加一個#號。
# --------
# 這是注釋塊
# --------
打印輸出
echo: 是Shell的一個內部指令,用於在屏幕上打印出指定的字符串。
echo arg
echo -e arg #執行arg里的轉義字符。echo加了-e默認會換行
echo arg > myfile #顯示結果重定向至文件,會生成myfile文件
注意,echo后單引號和雙引號作用是不同的。單引號不能轉義里面的字符。雙引號可有可無,單引號主要用在原樣輸出中。
printf:格式化輸出語句。
printf
命令用於格式化輸出, 是echo
命令的增強版。它是C語言printf()
庫函數的一個有限的變形,並且在語法上有些不同。
如同 echo
命令,printf
命令也可以輸出簡單的字符串:
printf "hello\n"
printf
不像 echo
那樣會自動換行,必須顯式添加換行符(\n)。
注意:printf
由 POSIX 標准所定義,移植性要比 echo
好。
printf 命令的語法:
printf format-string [arguments...]
#format-string 為格式控制字符串,arguments 為參數列表。功能和用法與c語言的 printf 命令類似。
這里僅說明與C語言printf()函數的不同:
- printf 命令不用加括號
- format-string 可以沒有引號,但最好加上,單引號雙引號均可。
- 參數比格式控制符(%)多時,格式控制符可以重用,可以將所有參數都轉換。
- arguments 使用空格分隔,不用逗號。
# 雙引號
printf "%d %s\n" 10 "abc"
10 abc
# 單引號與雙引號效果一樣
printf '%d %s\n' 10 "abc"
10 abc
# 沒有引號也可以輸出
printf %s abc
abc
# 但是下面的會出錯:
printf %d %s 10 abc
#因為系統分不清楚哪個是參數,這時候最好加引號了。
# 格式只指定了一個參數,但多出的參數仍然會按照該格式輸出,format-string 被重用
$ printf %s a b c
abc
$ printf "%s\n" a b c
a
b
c
# 如果沒有 arguments,那么 %s 用NULL代替,%d 用 0 代替
$ printf "%s and %d \n"
and 0
# 如果以 %d 的格式來顯示字符串,那么會有警告,提示無效的數字,此時默認置為 0
$ printf "The first program always prints'%s,%d\n'" Hello Shell
-bash: printf: Shell: invalid number
The first program always prints 'Hello,0'
$
read: 命令行從輸入設備讀入內容
#!/bin/bash
# Author : lalal
echo "What is your name?"
read NAME #輸入
echo "Hello, $NAME"
運行腳本:
chmod +x test.sh
./test.sh
What is your name?
lalal
Hello, lalal
變量定義
Shell支持自定義變量。
定義變量
定義變量時,變量名不加美元符號($),如:
variableName="value"
注意,變量名和等號之間不能有空格,這可能和你熟悉的所有編程語言都不一樣。有空格會出錯。
同時,變量名的命名須遵循如下規則:
- 首個字符必須為字母(a-z,A-Z)。
- 中間不能有空格,可以使用下划線(_)。
- 不能使用標點符號。
- 不能使用bash里的關鍵字(可用help命令查看保留關鍵字)。
變量定義舉例:
myUrl="lalal"
myNum=100
使用變量
使用一個定義過的變量,只要在變量名前面加美元符號($)即可,如:
your_name="lalal"
echo $your_name
echo ${your_name}
變量名外面的花括號是可選的,加不加都行,加花括號是為了幫助解釋器識別變量的邊界,比如下面這種情況:
for skill in C PHP Python Java
do
echo "I am good at ${skill}Script"
done
如果不給skill變量加花括號,寫成echo "I am good at $skillScript"
,解釋器就會把$skillScript
當成一個變量(其值為空),代碼執行結果就不是我們期望的樣子了。
推薦給所有變量加上花括號,這是個好的編程習慣。
已定義的變量,可以被重新定義。
在變量前面加readonly
命令可以將變量定義為只讀變量,只讀變量的值不能被改變。
url="http://www.baidu.com"
readonly url
url="http://www.baidu.com"
使用 unset
命令可以刪除變量。語法:
unset variable_name
變量被刪除后不能再次使用;unset 命令不能刪除只讀變量。
變量類型
運行shell時,會同時存在三種變量:
1) 局部變量
局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啟動的程序不能訪問局部變量。
2) 環境變量
所有的程序,包括shell啟動的程序,都能訪問環境變量,有些程序需要環境變量來保證其正常運行。必要的時候shell腳本也可以定義環境變量。
3) shell變量
shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行。
特殊變量
前面已經講到,變量名只能包含數字、字母和下划線,因為某些包含其他字符的變量有特殊含義,這樣的變量被稱為特殊變量。
變量 | 含義 |
---|---|
$0 |
當前腳本的文件名 |
$n |
傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1 ,第二個參數是$2 。 |
$# |
傳遞給腳本或函數的參數個數。 |
$* |
傳遞給腳本或函數的所有參數。 |
$@ |
傳遞給腳本或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同 |
$? |
上個命令的退出狀態,或函數的返回值。 |
$$ |
當前Shell進程ID。對於 Shell 腳本,就是這些腳本所在的進程ID。 |
示例:
#!/bin/bash
echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"
運行結果:
$./test.sh Zara Ali
File Name : ./test.sh
First Parameter : Zara
Second Parameter : Ali
Quoted Values: Zara Ali
Quoted Values: Zara Ali
Total Number of Parameters : 2
$*
和 $@
的區別
$*
和 $@
都表示傳遞給函數或腳本的所有參數,不被雙引號(" ")包含時,都以"$1" "$2" … "$n"
的形式輸出所有參數。
但是當它們被雙引號(" ")包含時,"$*
" 會將所有的參數作為一個整體,以"$1 $2 … $n
"的形式輸出所有參數;"$@
" 會將各個參數分開,以"$1" "$2" … "$n"
的形式輸出所有參數。
示例:
#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
echo "$var"
done
echo "print each param from \$@"
for var in $@
do
echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
echo "$var"
done
執行 ./test.sh "a" "b" "c" "d"
,看到下面的結果:
$*= a b c d
"$*"= a b c d
$@= a b c d
"$@"= a b c d
print each param from $*
a
b
c
d
print each param from $@
a
b
c
d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d
退出狀態
$?
可以獲取上一個命令的退出狀態。所謂退出狀態,就是上一個命令執行后的返回結果。
示例:
if [[ $? != 0 ]];then
echo "error"
exit 1;
fi
退出狀態是一個數字,一般情況下,大部分命令執行成功會返回 0,失敗返回 1。
不過,也有一些命令返回其他值,表示不同類型的錯誤。
轉義字符
轉義字符 含義
\\ 反斜杠
\a 警報,響鈴
\b 退格(刪除鍵)
\f 換頁(FF),將當前位置移到下頁開頭
\n 換行
\r 回車
\t 水平制表符(tab鍵)
\v 垂直制表符
shell默認是不轉義上面的字符的。需要加-e
選項。
舉個例子:
#!/bin/bash
a=11
echo -e "a is $a \n"
運行結果:
Value of a is 10
這里 -e
表示對轉義字符進行替換。如果不使用 -e
選項,將會原樣輸出:
Value of a is 10\n
可以使用 echo 命令的 -E
選項禁止轉義,默認也是不轉義的;使用 -n
選項可以禁止插入換行符。
命令替換
命令替換是指Shell可以先執行命令,將輸出結果暫時保存,在適當的地方輸出。
語法:
`command`
注意是反引號,不是單引號,這個鍵位於 Esc 鍵下方。
下面的例子中,將命令執行結果保存在變量中:
#!/bin/bash
DATE=`date`
echo "Date is $DATE"
變量替換
變量替換可以根據變量的狀態(是否為空、是否定義等)來改變它的值。
可以使用的變量替換形式:
形式 | 說明 |
---|---|
${var} |
變量本來的值 |
${var:-word} |
如果變量 var 為空或已被刪除(unset),那么返回 word,但不改變 var 的值。 |
${var:=word} |
如果變量 var 為空或已被刪除(unset),那么返回 word,並將 var 的值設置為 word。 |
${var:?message} |
如果變量 var 為空或已被刪除(unset),那么將消息 message 送到標准錯誤輸出,可以用來檢測變量 var 是否可以被正常賦值。若此替換出現在Shell腳本中,那么腳本將停止運行。 |
${var:+word} |
如果變量 var 被定義,那么返回 word,但不改變 var 的值。 |
一個完整的shell示例
下面的腳本用於php安裝過程中安裝zip擴展。
php_zip_ins.sh
#!/bin/bash
#zip install
if [ -d php-5.4.25/ext/zip ];then
cd php-5.4.25/ext/zip
else
tar zxvf php-5.4.25.tar.gz
cd php-5.4.25/ext/zip
fi
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make
[ $? != 0 ] && exit
make install
echo
grep 'no-debug-zts-20100525' /usr/local/php/etc/php.ini
if [ $? != 0 ];then
echo '' >> /usr/local/php/etc/php.ini
echo 'extension_dir=/usr/local/php/lib/php/extensions/no-debug-zts-20100525' >> /usr/local/php/etc/php.ini
fi
grep 'zip.so' /usr/local/php/etc/php.ini
if [ $? != 0 ];then
echo 'extension=zip.so' >> /usr/local/php/etc/php.ini
fi
echo "zip install is OK"
/usr/local/apache2/bin/apachectl restart
cd -
rm -rf php-5.4.25
echo "all ok!"
ls /usr/local/php/lib/php/extensions/no-debug-zts-20100525/
Shell腳本學習系列教程github: https://github.com/52fhy/shell-book