shell腳本編程之基礎篇(二)

shell腳本編程之基礎篇(二)node

==============================================================================正則表達式

概述:shell


==============================================================================express

退出狀態

進程使用退出狀態來報告成功或失敗編程

0 表明成功,1-255表明失敗centos

$? 變量保存最近的命令退出狀態 (查看:echo $?)存的是最後一條命令的結果,中間即便有錯誤,也無論。數組

腳本的狀態返回值bash

默認是腳本中執行的最後一條命令的狀態返回值;less

自定義狀態退出狀態碼;
ide

  • exit[n]:自定義退出狀態碼;(exit退出的是當前shell)

注意:

  • 腳本中一旦遇到exit命令,腳本會當即終止;終止退出狀態取決於exit命令後面的數字

  • 若是未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決於腳本中執行的最後一條命令的狀態碼

演示:  

 1.進程使用退出狀態

-c1表明一個數據包,-W表明一秒鐘
[root@centos7 ~]# ping -c1 -W1 192.168.1.116 &> /devnull
[root@centos7 ~]# echo $?
0   # 成功,此主機正在使用


[root@centos7 ~]# ping -c1 -W1 192.168.1.112 &> /devnull
[root@centos7 ~]# echo $?
1   # 失敗,此主機沒有使用

條件測試

做用:

  • 判斷某需求是否知足,須要由測試機制來實現;

  • 專用的測試表達式須要由測試命令輔助完成測試過程;

如何編寫測試表達式以實現所需的測試:

執行命令,並利用狀態返回值來判斷:

  • 0:成功

  • 1-255:失敗

測試表達式:

  • test EXPRESSION;

  • [ EXPRESSION ];

  • ` EXPRESSION `;特定狀況下使用。最穩妥(支持正則表達式)

注意:

  • EXPRESSION先後必須有空白字符,不然語法錯誤。

條件性的執行邏輯操做符

根據退出狀態而定,命令能夠有條件地運行

  • && :表明條件性的AND THEN;

  • || :表明條件性的OR ELSE

演示:

[root@centos7 ~]# ping -c1 -W1 192.168.1.1 &> /dev/null && echo "The host is up"
The host is up

# 表示 若是能 ping 通這個主機 就輸出 up,不能就輸出 down;必定是先與後或
[root@centos7 ~]# ping -c1 -W1 192.168.1.1 &> /dev/null && echo "The host is up" || echo "The host is down"
The host is up

[root@centos7 ~]# ping -c1 -W1 192.168.1.114 &> /dev/null && echo "The host is up" || echo "The host is down"
The host is down

# 表示 若是能 ping 通這個主機 就輸出 up,不能就輸出 down,且返回值爲 220。這裏的括號表示在子shell中執行
[root@centos7 ~]# ping -c1 -W1 192.168.1.114 &> /dev/null && echo "The host is up" || (echo "The host is down" ;exit 220)
The host is down
[root@centos7 ~]# echo $?
220

bash的測試類型(數值,字符串,文件測試)

 1.數值測試

數值測試

做用:數值比較

操做符

  • -eq:是否等於;[ $num1 -eq $num2 ];

  • -ne:是否不等於;

  • -gt:是否大於;

  • -ge:是否大於等於;

  • -lt:是否小於;

  • -le:是否小於等於;

演示:

[root@centos7 ~]# test 2 -eq 3
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# test 2 -ne 3
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# test 2 -gt 3
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# test 2 -lt 3
[root@centos7 ~]# echo $?
0

 2.字符串測試

字符串測試

  • 字符串比較要加引號;

  • 儘可能要使用` `

操做符 

  • ==:是否等於;

  • >:ascii碼是否大於ascii碼;

  • <:ascii碼是否小於ascii碼

  • !=:是否不等於;

  • =~:左側字符串是否可以被右側的PATTERN所匹配(擴展表達式)

  • -z "STRING":判斷指定的字符串是否爲空,空爲真,不空爲假,字符串必定要加雙引號;

  • -n "STRING":判斷指定的字符串是否不空,不空爲真,空爲假;

注意:

  • 字符串比較要加引號,表示引用,作變量替換要加雙引號,不作變量替換用單引號

  • 要儘可能使用 ` `

  • 在 [ ] 中作變量替換必定要加雙引號,可是若是使用 ` ` ,能夠不加引號

演示:

[root@centos7 ~]# [ tom == Tom ]
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# [ tom == tom ]
[root@centos7 ~]# echo $?
0

# 變量替換要儘可能用雙引號,若是不用的話,若是變量不存在爲空,會報錯
[root@centos7 ~]# [ tom == $name ]
-bash: [: tom: 期待一元表達式
[root@centos7 ~]# [ tom == "$name" ]  
[root@centos7 ~]# echo $?
1
[root@centos7 bin]# [[ tom == $name ]]
[root@centos7 bin]# echo $?
1

[root@centos7 ~]# name=xiu
[root@centos7 ~]# [ tom == $name ]
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# [ tom == "$name" ]
[root@centos7 ~]# echo $?
1

# 要儘可能使用 [[ ]]
[root@centos7 ~]# [ 'a' > 'b' ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [ 'a' < 'b' ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [[ 'a' > 'b' ]]
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# [[ 'a' < 'b' ]]
[root@centos7 ~]# echo $?
0

# 在 [] 中變量替換必定要加雙引號,可是在 [[ ]] 中能夠不加
[root@centos7 bin]# [ -z $a ] && echo yes || echo no
yes
[root@centos7 bin]# [ -n $a ] && echo yes || echo no
yes
[root@centos7 bin]# [ -n "$a" ] && echo yes || echo no
no
[root@centos7 bin]# [ -z "$a" ] && echo yes || echo no
yes
[root@centos7 bin]# [[ -n $a ]] && echo yes || echo no
no
[root@centos7 bin]# [[ -z $a ]] && echo yes || echo no
yes
#============================================================================

[root@centos7 ~]# name=haha
[root@centos7 ~]# echo $name
haha
[root@centos7 ~]# [[ "$name" =~ ha ]]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [[ "$name" =~ h ]]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [[ "$name" =~ hx ]]
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# [[ "$name" =~ xx ]]
[root@centos7 ~]# echo $?
1

 3.文件測試

存在性測試

  • -a FILE:同-e

  • -e FILE:文件存在性測試,存在爲真,不然爲假;

存在性及類型測試

  • -b FILE:是否存在且爲塊設備文件;

  • -c FILE:是否存在且爲字符設備文件;

  • -d FILE:是否存在且爲目錄文件;

  • -f FILE:是否存在且爲普通文件;

  • -h FILE 或-L FILE:存在且爲符號連接文件;

  • -p FILE:是否存在且爲命名管道文件;

  • -S FILE:是否存在且爲套接字文件;

文件權限測試

  • -r FILE:是否存在且對當前用戶可讀;

  • -w FILE:是否存在且對當前用戶可寫;

  • -x FILE:是否存在且當前用戶可執行

文件特殊權限測試

  • -g FILE:是否存在且擁有sgid權限;

  • -u FILE:是否存在且擁有suid權限;

  • -k FILE:是否存在且擁有sticky權限;

文件是否有內容

  • -s FILE:是否存在且非空(即,文件是否有內容);

文件時間戳測試

  • -N FILE:文件自從上一次讀操做後是否被修改過;

從屬關係測試

  • -O FILE:當前用戶是否爲文件的屬主;

  • -G FILE:當前用戶是否屬於文件的屬組;

文件是否打開

  • -t fd:fd表示文件描述符是否已經打開且與某終端相關;

雙目測試

  • FILE1 -ef FILE2:FILE1與FILE2是否指向同一個設備上的相同inode;

  • FILE1 -nt FILE2:FILE1是否新於FILE2;(修改時間)

  • FILE1 -ot FILE2:FILE1是否舊於FILE2;

注意:

  • 文件測試通常使用 [ ] 就能夠

演示:

 1.文件存在性測試

[root@centos7 ~]# [ -e /etc/fstab ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [ -e /etc/rc.d/rc.sysinit ]
[root@centos7 ~]# echo $?
1

 2.文件存在性及類型測試     

[root@centos7 ~]# [ -b /dev/sda ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [ -b /dev/sdb ]
[root@centos7 ~]# echo $?
1
[root@centos7 ~]# [ -d /etc ]
[root@centos7 ~]# echo $?
0

[root@centos7 ~]# [ -L /etc/redhat-release ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# ll /etc/redhat-release 
lrwxrwxrwx. 1 root root 14 11月  6 18:30 /etc/redhat-release -> centos-release

 3.文件權限及特殊權限測試      

[root@centos7 ~]# ll /etc/shadow
---------- 1 root root 1400 2月  20 14:12 /etc/shadow

[centos@centos7 ~]$ whoami
centos
[centos@centos7 ~]$ [ -r /etc/shadow ]
[centos@centos7 ~]$ echo $?
1
[centos@centos7 ~]$ [ -r /etc/passwd ]
[centos@centos7 ~]$ echo $?
0
[centos@centos7 ~]$ [ -w /etc/passwd ]
[centos@centos7 ~]$ echo $?
1

# 對於root用戶來說,rw 權限是以實際爲主,但執行權限是起做用的
[root@centos7 ~]# whoami
root
[root@centos7 ~]# [ -r /etc/shadow ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [ -w /etc/shadow ]
[root@centos7 ~]# echo $?
0
[root@centos7 ~]# [ -x /etc/shadow ]
[root@centos7 ~]# echo $?
1

#==========================================================================

[root@centos7 ~]# [ -u /usr/bin/passwd ]
[root@centos7 ~]# echo $?
0 # 說明 /usr/bin/passwd  擁有suid權限

[root@centos7 ~]# ll /usr/bin/passwd 
-rwsr-xr-x. 1 root root 27832 6月  10 2014 /usr/bin/passwd

4.文件是否有內容測試

[root@centos7 ~]# touch /tmp/hello
[root@centos7 ~]# [ -s /tmp/hello ]
[root@centos7 ~]# echo $?
1

[root@centos7 ~]# [ -s /etc/fstab ]
[root@centos7 ~]# echo $?
0

5.雙目測試

[root@centos7 ~]# touch f1
[root@centos7 ~]# ln f1 f22 # 建立f22 的硬連接爲f1

[root@centos7 ~]# [ f1 -ef f22 ]  # 是否指向同一設備上相同的inode,也就是說是否爲硬連接
[root@centos7 ~]# echo $?
0

[root@centos7 ~]# ll -i f1 f22
201391291 -rw-r--r-- 2 root root 1024 2月  23 18:39 f1
201391291 -rw-r--r-- 2 root root 1024 2月  23 18:39 f22

 4.組合測試條件

第一種方式:邏輯判斷符

  • OMMAND1 && COMMAND2 :而且;

  • COMMAND1 || COMMAND2   :或者;

  • !COMMAND :

示例:

  • [ -O FILE ] && [ -r FILE ]

第二種方式:布爾運算符

  • EXPRESSION1 -a EXPRESSION2 :而且

  • EXPRESSION1 -o EXPRESSION2 :或者

  • ! EXPRESSION:取反

注意:

  •  布爾運算符(-a ,-o, !)只能用在 [ ] 表達式中;如:[ 1 -eq 1 -a 2 -eq 2 ]爲true;[ 1 -eq 1 -o 2 -eq 1 ]爲true

  • 邏輯運算符(&&, ||)只能用在 ` `和(( ))中使用

總結:

1.條件表達式

表達式

示例

[ expression ] [ 1 -eq 1 ] 
` expression ` ` 1 -eq 1 `
test expression test 1 -eq 1 ,等同於[]

2.整數比較符

比較符

描述

示例

-eq,equal 等於 [ 1 -eq 1 ]爲true
-ne,not equal 不等於 [ 1 -ne 1 ]爲false
-gt,greater than 大於 [ 2 -gt 1 ]爲true
-lt,lesser than 小於 [ 2 -lt 1 ]爲false
-ge,greater or equal 大於或等於 [ 2 -gt 1 ]爲true
-le,lesser or equal 小於或等於 [ 2 -le 1 ]爲false

3.字符串比較符

運算符

描述

示例

== 等於 [ "a" == "a"  ]爲true
!= 不等於 [ "a" != "a"  ]爲false
> 大於,判斷字符串時根據ASCII碼錶順序,不經常使用

在[]表達式中:[ 2 \> 1 ]爲true

在[[]]表達式中:[[ 2 > 1 ]]爲true

在(())表達式中:(( 3 > 2 ))爲true

< 小於,判斷字符串時根據ASCII碼錶順序,不經常使用

在[]表達式中:[ 2 \< 1 ]爲false

在[[]]表達式中:[[ 2 < 1 ]]爲false

在(())表達式中:(( 3 < 2 ))爲false

>= 大於等於 在(())表達式中:(( 3 >= 2 ))爲true
<= 小於等於 在(())表達式中:(( 3 <= 2 ))爲false
-n 字符串長度不等於0爲真

VAR1=1;VAR2=""

[ -n "$VAR1" ]爲true

[ -n "$VAR2" ]爲false

-z 字符串長度等於0爲真

VAR1=1;VAR2=""

[ -z "$VAR1" ]爲false

[ -z "$VAR2" ]爲true

str 字符串存在爲真

VAR1=1;VAR2=""

[ $VAR1 ]爲true

[ $VAR2 ]爲false

 

4.文件測試

測試符

描述

示例

-e 文件或目錄存在爲真 [ -e path ] path存在爲true
-f 文件存在爲真 [ -f file_path ] 文件存在爲true
-d 目錄存在爲真 [ -d dir_path ] 目錄存在爲true
-r 有讀權限爲真 [ -r file_path ] file_path有讀權限爲true
-w 有寫權限爲真 [ -w file_path ] file_path有寫權限爲true
-x 有執行權限爲真 [ -x file_path ] file_path有執行權限爲true
-s 文件存在而且大小大於0爲真 [ -s file_path ] file_path存在而且大小大於0爲true

5.布爾運算符

運算符

描述

示例

! 非關係,條件結果取反 [ ! 1 -eq 2 ]爲true
-a 和關係,在[]表達式中使用 [ 1 -eq 1 -a 2 -eq 2 ]爲true
-o 或關係,在[]表達式中使用 [ 1 -eq 1 -o 2 -eq 1 ]爲true

6.邏輯判斷符

判斷符

描述

示例

&& 邏輯與,在` `和(( ))表達式中或判斷表達式是否爲真時使用

[[ 1 -eq 1 && 2 -eq 2 ]]爲true

(( 1 == 1 && 2 == 2 ))爲true

[ 1 -eq 1 ] && echo yes 表示:若是&&前面表達式爲true則執行後面的

|| 邏輯或,在` `和(( ))表達式中或判斷表達式是否爲真時使用

[[ 1 -eq 1 || 2 -eq 1 ]]爲true

(( 1 == 1 || 2 == 2 ))爲true

[ 1 -eq 2 ] || echo yes 表示:若是||前面表達式爲false則執行後面的

7.整數運算

運算符

描述

+ 加法
- 減法
* 乘法
/ 除法
% 取餘


運算表達式

示例

$(()) $((1+1))
$[] $[1+1]


除了Shell自己的算數運算表達式,還有幾個命令支持複雜的算數運算:

命令

描述

示例

let 賦值並運算,支持++、--

let VAR=(1+2)*3 ; echo $VAR

x=10 ; y=5

let x++;echo $x 每執行一次x加1

let y--;echo $y 每執行一次y減1

let x+=2 每執行一次x加2

let x-=2 每執行一次x減2

expr 乘法*須要加反斜槓轉義\*

expr 1 \* 2  運算符兩邊必須有空格

expr \( 1 + 2 \) \* 2  使用雙括號時要轉義

bc 計算器,支持浮點運算、平方等

bc自己就是一個計算器,可直接輸入命令,進入解釋器。

echo 1 + 2 |bc 將管道符前面標準輸出做爲bc的標準輸入

echo "1.2+2" |bc

echo "10^10" |bc 

echo 'scale=2;10/3' |bc  用scale保留兩位小數點





看到這裏,想想裏面所講的小括號、中括號的用途,是否是有點懵逼了。那咱們總結一下!

( )

用途1:在運算中,先計算小括號裏面的內容

用途2:數組

用途3:匹配分組

(( ))

用途1:表達式,不支持-eq這類的運算符。不支持-a和-o,支持<=、>=、<、>這類比較符和&&、||

用途2:C語言風格的for(())表達式

$( ) 執行Shell命令,與反撇號等效
$(( ))

用途1:簡單算數運算

用途2:支持三目運算符 $(( 表達式?數字:數字 ))

[ ] 條件表達式,裏面不支持邏輯判斷符(&&,|| )
` ` 條件表達式,裏面不支持-a和-o,不支持<=和>=比較符,支持-eq、<、>這類比較符。支持=~模式匹配,也能夠不用雙引號也不會影響原意,比[]更加通用
$[ ] 簡單算數運算
{ } 對逗號(,)和點點(...)起做用,好比touch {1,2}建立1和2文件,touch {1..3}建立一、2和3文件
${ }

用途1:引用變量

用途2:字符串處理

          



練習:

  一、編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操做系統版本,內核版本,CPU型號,內存大小,硬盤大小。


[root@centos7 bin]# cat systeminfo.sh 
#!/bin/bash

# 取 IP 地址,採用sed方法,掐頭去尾
server_ip=$(ifconfig |sed -n '2p' |sed -e 's@^.*inet@@' -e 's@net.*@@')
CPUmod=$(lscpu | grep -i "model name:")
Meninfo=$(free -h | sed -n '2p' | tr -s ' ' | cut -d' ' -f2)
DISKinfo=$(fdisk -l |grep "Disk /dev/[sh]d[a-z]" |sed -r 's@.* ([0-9]+.*GB).*@\1@')

echo 'hostname :'$(hostname)
echo 'hostIP:'$server_ip
echo 'OS version:'$(cat /etc/redhat-release)
echo 'Kernel version:'$(uname -r)
echo 'CPU '$CPUmod
echo 'Memory :'$Meninfo
echo 'Harddisk:'$DISKinfo

# 執行腳本
[root@centos7 bin]# chmod +x systeminfo.sh
[root@centos7 bin]# ll systeminfo.sh
-rwxr-xr-x 1 root root 522 Feb 23 21:42 systeminfo.sh
[root@centos7 bin]# cd
[root@centos7 ~]# systeminfo.sh
hostname :centos7
hostIP: 192.168.1.112
OS version:CentOS Linux release 7.2.1511 (Core)
Kernel version:3.10.0-327.el7.x86_64
CPU Model name: Intel(R) Core(TM) i3-2328M CPU @ 2.20GHz
Memory :977M
Harddisk:85.9 GB
相關文章
相關標籤/搜索