shell編程基礎:構建基礎腳本(1)

內容列表

1. 使用多個命令

方式 樣式 介紹
使用;連接兩條命令 command1 ; command2 第一條失敗後,第二條仍然執行
使用&&連接兩條命令 command1 && command2 第一條失敗後,第二條不會執行
# 1. 使用;分隔兩個命令
[root@vm14 ~]# date ; pwd
2020年 03月 29日 星期日 21:18:41 CST
/root
# 使用;進行分隔的命令,當第一條失敗後,第二條仍然會執行
[root@vm14 ~]# date %m ; pwd
date: 無效的日期"%m"
/root

# 2. 使用&&連接
[root@vm14 ~]# date && pwd
2020年 03月 29日 星期日 21:20:31 CST
/root
# 使用&&連接的兩條命令,第一條失敗後,第二條不會繼續執行
[root@vm14 ~]# date %m && pwd
date: 無效的日期"%m"

2. 創建腳本文件

shell腳本第一行內容格式爲:#!/bin/bash,用於指定執行腳本所使用的的shell(shell有多種,此處指定使用bash執行)。當然第一行內容可以缺失,執行時會使用用戶的默認shell執行。
我們通過vim創建第一個測試腳本/root/shell/test1.sh,內容如下:

#!/bin/bash
# 這一行是註釋內容,shell中以#開頭的都是註釋(不包括第一行shell類型聲明)
date
pwd

在目錄/root/shell下腳本執行:

# 方式1,使用sh進行執行
[root@vm14 shell]# sh test1.sh 
2020年 03月 29日 星期日 21:36:40 CST
/root/shell


# 方式2,使用相對路徑進行執行
[root@vm14 shell]# chmod u+x test1.sh 
[root@vm14 shell]# ./test1.sh 
2020年 03月 29日 星期日 21:40:02 CST
/root/shell


# 方式3,將/root/shell配置到PATH中,然後使用文件名進行調用
# 3.1 將/root/shell加入PATH
cat >> ~/.bash_profile << EOF
PATH=\$PATH:/root/shell
export PATH
EOF
# 3.2 使PATH生效
[root@vm14 shell]# source ~/.bash_profile
# 3.3 查看PATH,如果輸出內容包含/root/shell則說明設置成功
[root@vm14 shell]# echo $PATH 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/shell
# 3.4 執行shell(需要進行權限修改)
[root@vm14 shell]# test1.sh 
2020年 03月 29日 星期日 21:50:17 CST
/root/shell


# 方式4,一般情況下~/bin已經被加入到PATH中,也就是我們只需要在~(用戶home)下創建bin目錄,然後在bin下創建shell腳本便可直接執行

3. 顯示消息

# 使用echo將信息顯示到控制檯,字符串無需用引號(’|")進行標示
[root@vm14 shell]# echo this is a test message
this is a test message
# 當內容有單引號時,用雙引號標示字符串
[root@vm14 shell]# echo "this's a ' message"
this's a ' message
# 當內容有雙引號時,用單引號標示字符串
[root@vm14 shell]# echo 'this is a "" message'
this is a "" message
# 同時包含時
[root@vm14 shell]# echo "this'"'s a " message'
this's a " message

創建腳本/root/shell/test2.sh,內容如下

#!/bin/bash
# 輸出當前時間
echo '當前時間是:'
date

腳本執行:

# 在/root/shell下執行
[root@vm14 shell]# sh test2.sh 
當前時間是:
2020年 03月 29日 星期日 22:08:00 CST
# 上面的輸出中描述與時間不在一行,可以將腳本中echo命令第一個參數改成-n使其輸出到一行
# echo -n '當前時間是:'
[root@vm14 shell]# sh test2.sh 
當前時間是:2020年 03月 29日 星期日 22:10:59 CST

4. 使用變量

4.1 環境變量

shell維護着一組環境變量,用來記錄特定的系統信息。比如系統的名稱、登錄到系統上的用
戶名、用戶的系統ID(也稱爲UID)、用戶的默認主目錄以及shell查找程序的搜索路徑。可以用
set命令來顯示一份完整的當前環境變量列表。

[root@vm14 shell]# set 
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
# 省略
USER=root
XDG_RUNTIME_DIR=/run/user/0
XDG_SESSION_ID=17
_=test2.sh
colors=/root/.dir_colors

獲取系統變量

# 顯示用戶名
[root@vm14 shell]# echo 用戶名:$USER
用戶名:root
# 顯示home
[root@vm14 shell]# echo home:$HOME
home:/root
# 轉義字符使用,使用\可以使$不再解讀爲取變量值
[root@vm14 shell]# echo 商品價格:$15
商品價格:5
[root@vm14 shell]# echo 商品價格:\$15
商品價格:$15

4.2 用戶變量

# 定義變量
[root@vm14 shell]# var1=第一個變量
[root@vm14 shell]# var2=第二個變量
[root@vm14 shell]# echo $var1
第一個變量
[root@vm14 shell]# echo $var1 $var2
第一個變量 第二個變量

4.3 命令替換

命令替換:將命令執行結果賦值給變量

# 方式1,使用`符號
[root@vm14 shell]# var1=`date`
[root@vm14 shell]# echo $var1
2020年 03月 29日 星期日 22:25:46 CST
# 方式2,使用$()
[root@vm14 shell]# var2=$(date)
[root@vm14 shell]# echo $var2
2020年 03月 29日 星期日 22:26:28 CST

應用示例

# 根據日期生成日誌文件
[root@vm14 shell]# touch $(date +%Y%m%d).log
# 查看生成文件
[root@vm14 shell]# ls
20200329.log  test1.sh  test2.sh

命令替換會創建一個子shell來運行對應的命令。子shell( subshell)是由運行該腳本的shell
所創建出來的一個獨立的子shell( child shell)。正因如此,由該子shell所執行命令是無法
使用腳本中所創建的變量的。
在命令行提示符下使用路徑./運行命令的話,也會創建出子shell;要是運行命令的時候
不加入路徑,就不會創建子shell。如果你使用的是內建的shell命令,並不會涉及子shell。
在命令行提示符下運行腳本時一定要留心!

5. 輸入輸出重定向

5.1 輸出重定向

# > 覆蓋重定向, command > outputfile
# 將date命令的結果輸出到date.log文件中(會覆蓋之前內容)
[root@vm14 shell]# date > date.log
[root@vm14 shell]# cat date.log 
2020年 03月 29日 星期日 22:35:03 CST

# >> 追加重定向, command >> outputfile
# 將date命令的結果輸出到date.log文件中(不覆蓋之前內容)
[root@vm14 shell]# date >> date.log
[root@vm14 shell]# cat date.log 
2020年 03月 29日 星期日 22:35:03 CST
2020年 03月 29日 星期日 22:36:40 CST

5.2 輸入重定向

# < 文件輸入重定向, command < inputfile
# 計算文件test1.sh的行數、詞數、字節數
[root@vm14 shell]# wc < test1.sh 
  4   5 121

# 內聯輸入重定向( inline input redirection),格式如下
command << marker
data
marker

# 示例:
wc << EOF
TEST 1
TEST 2
TEST3
EOF
# 上例中EOF爲使用的marker,可以自己定義,比如定義成 END
wc << END
TEST 1
TEST 2
TEST3
END
# 上面兩個效果是一致的

6. 管道

管道:將上個命令的輸出,傳遞給下個命令當做輸入。
格式:command1 | command2 ,將command1的輸出,傳遞給command2當做輸入

# 將date命令的輸出,傳遞給wc命令作爲輸入
[root@vm14 ~]# date | wc
      1       6      43
# ps -ef顯示全部進程,通過管道傳遞給grep命令,進行篩選
[root@vm14 ~]# ps -ef |grep ssh
root       6669      1  0 15:23 ?        00:00:00 /usr/sbin/sshd -D
root      62710   6669  0 21:42 ?        00:00:00 sshd: root@pts/0
root      62742  62715  0 21:44 pts/0    00:00:00 grep --color=auto ssh

7. 數學運算

7.1 expr命令

操作符與操作數之間必須要有空格,且僅支持整數運算

# 加法
[root@vm14 ~]# expr 1 + 1
2
# 減法
[root@vm14 ~]# expr 4 - 1
3
# 乘法,需要對*進行轉義
[root@vm14 ~]# expr 1 \* 4
4
# 除法
[root@vm14 ~]# expr 4 / 3
1

expr命令支持的所有命令符列表

7.2 方括號

格式:$[num1 操作符 num2],數字與操作符之間空隔可有可無,僅支持整數運算

# 加法
[root@vm14 ~]# echo $[1+2]
3
# 減法
[root@vm14 ~]# echo $[4 -1]
3
# 乘法,不需要對*進行轉義
[root@vm14 ~]# echo $[1*4]
4
# 除法
[root@vm14 ~]# echo $[4/3]
1

7.3 bash計算器

bash計算器能夠識別

  • 數字(整數和浮點數)
  • 變量(簡單變量和數組)
  • 註釋(以#或C語言中的/* */開始的行)
  • 表達式
  • 編程語句(例如if-then語句)
  • 函數

7.3.1 bash計算器初試:

# 安裝bash計算器
yum install bc
# 使用,命令行中輸入bc,然後回車
[root@vm14 ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'. 
# 加法:輸入1.1+2.11,然後回車
1.1+2.11
3.21
# 減法:輸入4.21-1.1,然後回車
4.21-1.1
3.11
# 乘法:輸入1.99*1.21,然後回車
1.99*1.21
2.40
# 除法:輸入4/3,然後回車
4/3
1
# 精度問題,上面的除法只保留了整數部分,可以通過scale=4來設置保留4位小數
scale=4
# 重算除法
4/3
1.3333
# 重算乘法
1.99*1.21
2.4079
# 使用quit命令退出
quit

7.3.2 腳本中使用bc

# 示例1,使用$()
[root@vm14 ~]# var1=$(echo 'scale=4; 1.99*1.1'|bc)
[root@vm14 ~]# echo $var1
2.189

# 示例2,使用``
[root@vm14 ~]# echo `echo "scale=4; $var1*$var2"|bc`
2.189

# 示例3 使用內聯輸入重定向
echo $(bc << EOF
1.99*1.1
EOF
)
# 返回值
2.18

8. 退出腳本

8.1 退出狀態碼

shell中運行的每個命令都使用退出狀態碼( exit status)告訴shell它已經運行完畢。退出狀態碼是一個0~ 255的整數值,在命令結束運行時由命令傳給shell。可以捕獲這個值並在腳本中使用。

Linux提供了一個專門的變量$?來保存上個已執行命令的退出狀態碼。

[root@vm14 ~]# date 
2020年 03月 30日 星期一 22:31:09 CST
# 查看date命令的狀態碼,按照慣例,一個成功結束的命令的退出狀態碼是0。
[root@vm14 ~]# echo $?
0

# 如果一個命令結束時有錯誤,退出狀態碼就是一個正數值。
[root@vm14 ~]# date %m
date: 無效的日期"%m"
[root@vm14 ~]# echo $?
1

Linux退出狀態碼列表

8.2 exit命令

默認情況下, shell腳本會以腳本中的最後一個命令的退出狀態碼退出。exit命令允許你在腳本結束時指定一個退出狀態碼。

自定義狀態碼示例:
創建腳本/root/shell/test3.sh,內容如下:

#!/bin/bash
# 自定義退出狀態碼
var1=10
var2=30
var3=$[$var1*$var2]
echo var3 is $var3
# 此處返回300 
exit $var3

執行腳本

[root@vm14 shell]# sh test3.sh 
var3 is 300
# 返回值是44,因爲狀態碼範圍是0-255,當返回值val超過這個範圍時返回:val % 256 > 0 ? val % 256 : val % 256 +256
# 此處val = 300 , 也就是返回300 % 256 =44
[root@vm14 shell]# echo $?
44


附錄:

expr命令符列表:

操作符 功能
ARG1 | ARG2 如果ARG1既不是null也不是零值,返回ARG1;否則返回ARG2
ARG1 & ARG2 如果沒有參數是null或零值,返回ARG1;否則返回0
ARG1 < ARG2 如果ARG1小於ARG2,返回1;否則返回0
ARG1 <= ARG2 如果ARG1小於或等於ARG2,返回1;否則返回0
ARG1 = ARG2 如果ARG1等於ARG2,返回1;否則返回0
ARG1 != ARG2 如果ARG1不等於ARG2,返回1;否則返回0
ARG1 >= ARG2 如果ARG1大於或等於ARG2,返回1;否則返回0
ARG1 > ARG2 如果ARG1大於ARG2,返回1;否則返回0
ARG1 + ARG2 返回ARG1和ARG2的算術運算和
ARG1 - ARG2 返回ARG1和ARG2的算術運算差
ARG1 * ARG2 返回ARG1和ARG2的算術乘積
ARG1 / ARG2 返回ARG1被ARG2除的算術商
ARG1 % ARG2 返回ARG1被ARG2除的算術餘數
STRING : REGEXP 如果REGEXP匹配到了STRING中的某個模式,返回該模式匹配
match STRING REGEXP 如果REGEXP匹配到了STRING中的某個模式,返回該模式匹配
substr STRING POS LENGTH 返回起始位置爲POS(從1開始計數)、長度爲LENGTH個字符的子字符串
index STRING CHARS 返回在STRING中找到CHARS字符串的位置;否則,返回0
length STRING 返回字符串STRING的數值長度
+ TOKEN 將TOKEN解釋成字符串,即使是個關鍵字
(EXPRESSION) 返回EXPRESSION的值

Linux退出狀態碼:

狀 態 碼 描 述
0 命令成功結束
1 一般性未知錯誤
2 不適合的shell命令
126 命令不可執行
127 沒找到命令
128 無效的退出參數
128+x 與Linux信號x相關的嚴重錯誤
130 通過Ctrl+C終止的命令
255 正常範圍之外的退出狀態碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章