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
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