Linux 筆記 - 第十二章 Shell 腳本
博客地址:http://www.moonxy.com
一、前言
常見的編程語言分為兩類:一類是編譯型語言,如:C、C++ 和 Java等,它們遠行前要經過編譯器的編譯。另一類是解釋型語言,不需要編譯,執行時,需要使用解釋器一行一行地解釋執行,如:awk、perl、python 和 shell 等。
Shell 是一種腳本語言,屬於上面提到的第二類語言,就必須有對應的解釋器來執行這些腳本,最常見的腳本解釋器是:bash。
在編寫 Shell 腳本時,我們不僅會用到很多的 Linux 命令、正則表達式、管道符、數據流重定向等語法規則,還需要把內部功能模塊化後通過邏輯語句進行處理,最終形成常見的 Shell 腳本。
1.1 查看系統支持的 Shell 種類
Linux 的 Shell 種類眾多,常見的有:
Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
可以通過查看 /etc/shells,知道當前系統所支持的所有 shell 類型及路徑,如下:
[root@ryan ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
……
Bourn Shell 是最早流行起來的一個 Shell 版本,其創始人是 Steven Bourn,為了紀念他而將其命名為 Bourn Shell,簡稱 sh。RedHat 系列的 Linux 發行版默認也安裝了 Bash,也就是 Bourne Again Shell,由於易用和免費,Bash 在日常工作中被廣泛使用。同時,Bash 也是大多數Linux 系統默認的 Shell。
1.2 查看當前用戶使用的 Shell 種類
可以通過執行 echo $SHELL 查看,如下:
[root@ryan ~]# echo $SHELL
/bin/bash
或者查看 /etc/passwd,以查看 root 用戶的 Shell 類型為例,如下:
[root@ryan ~]# cat /etc/passwd | grep ^root
root:x:0:0:root:/root:/bin/bash
最後一個:號後顯示的字段即為 root 用戶的登錄 shell 類型,此處為 bash。
也可以直接輸入命令 echo $0 查看,但需要註意的是並不是所有的 Shell 都支持,如下:
[root@ryan ~]# echo $0
-bash
當然也可以在當前環境變量中查看,如下:
[root@ryan ~]# env | grep SHELL
SHELL=/bin/bash
其實,查看當前用戶 Shell 種類的方法還有很多。
1.3 查看 Shell 版本
在獲得當前使用的 shell 的類型後,用戶可以直接使用 shell 相關的命令參數獲取其版本號,一般都可以使用 --version 參數來獲取 shell 的版本號,如下:
[root@ryan ~]# bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
二、常用 Shell 操作
2.1 命令 date
date 命令的常用的格式化選項:
date +%Y:表示以四位數字格式打印年份;
[root@ryan ~]# date +%Y
2018
date +%y:表示以兩位數字格式打印年份;
[root@ryan ~]# date +%y
18
date +%m:表示月份;
[root@ryan ~]# date +%m
04
date +%d:表示日期;
[root@ryan ~]# date +%d
14
date +%H:表示小時;
[root@ryan ~]# date +%M
13
date +%M:表示分鐘;
[root@ryan ~]# date +%M
04
date +%S:表示秒;
[root@ryan ~]# date +%S
46
date +%w:表示星期,如果結果顯示 0 則表示周日;
[root@ryan ~]# date +%w
6
date +%F:表示年月日;
[root@ryan ~]# date +%F
2018-04-14
date +%T:表示時分秒;
[root@ryan ~]# date +%T
14:08:57
date +"%Y-%m-%d %H:%M:%S",顯示如下:
[root@ryan ~]# date +"%Y-%m-%d %H:%M:%S"
2018-04-14 14:10:43
date +"%F %T",顯示和上面相同。
有時候會用到前一天的日期,如下:
[root@ryan ~]# date -d "-1 day" +"%d"
13
或者後一天的日期,如下:
[root@ryan ~]# date -d "+1 day" +"%d"
15
同理可以設置小時,分鐘等。
2.2 數學運算
數學運算的時候要用 [ ] 括起來,並且前面要加符號 $
[root@ryan ~]# a=2;b=3
[root@ryan ~]# ab=$[$a+$b]
[root@ryan ~]# echo $ab
5
定義變量的格式是:
變量名=變量值
定義之後引用該變量時要加上符號 $,如下:
$ab
如果變量的值是 shell 命令,則需要加反引號,它的作用是將引號中的字符串當成 shell 命令來執行。
2.3 和用戶交互
read 命令用於和用戶交互,它把用戶輸入的字符串作為變量值。如下:
[root@ryan shelltest]# cat readtest.sh
#!/bin/bash
## This Shell script is used for testing read
read -p "Please input a number:" n
echo $n
[root@ryan shelltest]# ./readtest.sh
Please input a number:5
5
也可添加 -t 選項,設置 3 秒後退出,如下:
read -t 3 -p "Please input a number:" n
2.4 Shell 腳本預設的特殊變量
$* 和 $@ 的區別為: $* 和 $@ 都表示傳遞給函數或腳本的所有參數,不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數。但是當它們被雙引號(" ")包含時,"$*" 會將所有的參數作為一個整體,以"$1 $2 … $n"的形式輸出所有參數;"$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數。
$? 可以獲取上一個命令的退出狀態。所謂退出狀態,就是上一個命令執行後的返回結果。退出狀態是一個數字,一般情況下,大部分命令執行成功會返回 0,失敗返回 1。
2.5 轉義字符
在 echo 中可以用於的轉義字符有:
2.6 Shell 中的引號
Shell 中的引號主要有單引號,雙引號和反引號。
單引號
單引號裏的任何字符都會原樣輸出,單引號字符串中的變量是無效的;
單引號字串中不能出現單引號(對單引號使用轉義符後也不行)。
雙引號
雙引號裏可以有變量;
雙引號裏可以出現轉義字符。
反引號
反引號中的字符串當成 shell 命令來執行。
得到文件名,使用 basename,如下:
[root@ryan shelltest]# basename /root/linux/shelltest/fortest.sh
fortest.sh
得到目錄名,使用 dirname,如下:
[root@ryan shelltest]# dirname /root/linux/shelltest/fortest.sh
/root/linux/shelltest
2.7 執行 Shell
有兩種方式可以執行 Shell,如下:
第一種:
sh filename.sh
第二種:
./filename.sh(需要有執行權限,所以一般要先授予 x 權限)
三、shell 運算符
3.1 算數運算符
原生 bash 不支持簡單的數學運算,但是可以通過其他命令來實現,例如 awk 和 expr。下面使用 expr 進行; expr 是一款表達式計算工具,使用它可以完成表達式的求值操作;
3.2 關系運算符
只支持數字,不支持字符串,除非字符串的值是數字。常見的有:
3.3 布爾運算符
-o(--or,也可以用 [ $a -lt 20 ] || [ $b -gt 100 ]),-a(--and,也可以用 [ $a -lt 20 ] && [ $b -gt 100 ])
3.4 字符串運算符
常用的有 -z,判斷變量的值是否存在,不存在返回 true,存在則返回 false。
3.5 文件測試運算符
常用的有 -e(--exist,判斷文件或目錄是否存在),-d(--directory,判斷是否目錄已經是否存在),-f(--file,判斷是否普通文件已經是否存在)
四、Shell 中的流程控制
4.1 if 條件選擇
[root@ryan shelltest]# cat iftest.sh
#! /bin/bash
## This shell script is used for testing if
echo "file name $(basename $0)"
echo "Hello $1"
echo "Hello $*"
echo "Args count: $#"
argscount=$#
if [ $argscount -eq 3 ];
then
echo ‘args count is correct‘
elif [ $argscount -gt 3 ];
then
echo ‘args count is more than 3‘
else
echo ‘args count is less than 3‘
fi
運行如下:
[root@ryan shelltest]# sh iftest.sh 3 5 a
file name iftest.sh
Hello 3
Hello 3 5 a
Args count: 3
args count is correct
[root@ryan shelltest]# sh iftest.sh 3 5
file name iftest.sh
Hello 3
Hello 3 5
Args count: 2
args count is less than 3
[root@ryan shelltest]# sh iftest.sh 3 5 a b
file name iftest.sh
Hello 3
Hello 3 5 a b
Args count: 4
args count is more than 3
4.2 case 條件選擇
[root@ryan shelltest]# cat casetest.sh
#!/bin/bash
## This shell script is used for testing case
read -p "Input a number:" n
a=$[$n%2]
case $a in
1)
echo "The number is odd."
;;
0)
echo "The number is even."
;;
*)
echo "It‘s not a number!"
;;
esac
運行如下:
[root@ryan shelltest]# sh casetest.sh
Input a number:4
The number is even.
[root@ryan shelltest]# sh casetest.sh
Input a number:5
The number is odd.
4.3 while 循環
[root@ryan shelltest]# cat whiletest.sh
#!/bin/bash
## This shell script is used for testing while
a=5
while [ "$a" -ge "1" ]; do
echo $a
a=$[$a-1]
done
運行如下:
[root@ryan shelltest]# sh whiletest.sh
5
4
3
2
1
4.4 for 循環
[root@ryan shelltest]# cat fortest.sh
#!/bin/bash
## This shell script is used for testing for
for file in `ls /root/linux/shelltest`;
do
ls -ld /root/linux/shelltest/$file
done
運行如下:
[root@ryan shelltest]# sh fortest.sh
-rwxr-xr-x 1 root root 233 Apr 14 17:33 /root/linux/shelltest/casetest.sh
-rw-r--r-- 1 root root 18 Apr 13 20:49 /root/linux/shelltest/field.properties
-rwxr-xr-x 1 root root 141 Apr 14 17:40 /root/linux/shelltest/fortest.sh
-rwxr-xr-x 1 root root 211 Apr 13 20:48 /root/linux/shelltest/funcomp.sh
-rwxr-xr-x 1 root root 235 Apr 13 20:47 /root/linux/shelltest/funtest.sh
-rwxr-xr-x 1 root root 321 Apr 13 20:46 /root/linux/shelltest/iftest.sh
-rwxr-xr-x 1 root root 101 Apr 14 14:37 /root/linux/shelltest/readtest.sh
-rwxr-xr-x 1 root root 113 Apr 13 20:46 /root/linux/shelltest/whiletest.sh
4.5 引入其他 Shell
方法一:使用 .
#!/bin/bash
. firstshell.sh
echo ‘your are in second file‘
方法二:使用 source
#!/bin/bash
source firstshell.sh
echo ‘your are in second file‘
4.6 Shell 中的中斷和繼續
break,用於循環中,表示退出該層循環到上一層;
continue,用於循環中,表示結束本次循環,開始下次循環;
exit,用在任何地方,表示退出 shell 腳本;
return,用在函數中,表示返回,退出函數;
這幾個命令與 C、Java 等語言中對應的關鍵字的作用一樣。
Linux 筆記 - 第十二章 Shell 腳本