老男孩shell教程(1-5章節)
關于檢視系統變量指令
set: 輸出所有的變量,包括全局變量和局部變量
env:隻顯示全局變量
declare:輸出所有的變量、函數、整數和已經導出(export)的變量
删除環境變量
unset 變量名
關于設定(全局)環境變量的三種方法
export 變量名=value
變量名=value ; export 變量名
declare -x 變量名=value
全局環境變量配置
/etc/profile/
/etc/bashrc/ (推薦在此檔案優先設定)
/etc/profile.d/ (登陸後初始化或顯示加載内容,檔案無需執行權限)
普通環境變量三種定義方法
變量名=value
變量名='value'
變量名="value"
shell中的特殊位置參數變量,請見下表
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLwYjNJRVVGRTcSlURBFkYzx0a6NjYtIjax02bpt0dvwlN58CXxkzLcFDMN9CXyAzcml3dvwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
關于特殊位置參數實戰
使用條件表達式判斷語句
# cat test_variable.sh
#!/bin/bash
#create by wutf
#Creation time 2018-10-18
[ $# -ne 2 ] && {
echo "must two args"
exit 1
}
echo "this is a test!"
當然腳本中的核心代碼,也可以寫成:
[ $# -ne 2 ] && {
echo "must two args"
exit 1
} || echo "this is a test!"
執行腳本:
[root@wtf tmp]# sh test_variable.sh wtf
must two args
[root@wtf tmp]# sh test_variable.sh wtf didi
this is a test!
[root@wtf tmp]# sh test_variable.sh
must two args
使用 if 判斷語句
#!/bin/bash
#create by wutf
#Creation time 2018-10-18
if [ $# -ne 2 ]
then
echo "USAGE:/bin/sh $0 arg1 arg2"
exit 2
else
echo "this is a test!"
fi
# sh test_variable.sh
USAGE:/bin/sh test_variable.sh arg1 arg2
# echo $?
2
# sh test_variable.sh wtf
USAGE:/bin/sh test_variable.sh arg1 arg2
# sh test_variable.sh wtf didi
this is a test!
# echo $?
0
關于 $@ 與 $* 的異同點
- 相同點:不帶引号時,即 $@ $* ,表示傳入腳本中參數的個數
- 不同點:添加引号,即 "$@" "$*" ,參考下面代碼執行個體
設定三個參數變量:
# set -- "I am" datagrand yunwei ## 通過 set 設定三個字元串參數,"--" 表示清除所有的參數變量,重新設定後面的參數變量
# echo $1
I am
# echo $2
datagrand
# echo $3
yunwei
使用 for 循環測試:
# for i in "$*";do echo $i;done
I am datagrand yunwei
# for i in "$@";do echo $i;done
I am
datagrand
yunwei
另外注意⚠️一個指令:shift (将位置參數移位,左移),如:
# echo $1
I am
# shift
# echo $1
datagrand
# echo $2
yunwei
# echo $3
bash shell 内置變量指令
常用的内部指令:
echo eval exec export read shift
echo 在螢幕上輸出資訊
指令格式:echo args # 可以是字元串和變量的組合
功能說明:将echo指令後面args指定的字元串及變量等顯示到标準輸出。
常見參數如下:
實戰--echo參數
# echo wutf
wutf
# echo -n wutf
wutf[root@wtf ~]#
# echo "wutf\tdatagrand\tdata\tgrand"
wutf\tdatagrand\tdata\tgrand
# echo -e "wutf\tdatagrand\tdata\tgrand"
wutf datagrand data grand
# echo -e "wutf\tdatagrand\ndata\tgrand" ## 等價于# printf "wutf\tdatagrand\ndata\tgrand\n"
wutf datagrand
data grand
說明⚠️:printf 功能更強大,當需要特殊負載的格式時才考慮使用printf。
eval
指令格式:eval cmd ==>cmd包含變量等指令
功能:當shell程式執行到eval語句時,shell讀入參數cmd,并将它們組合成一個新的指令,然後去執行。簡單點說,
就是eval會對後面的cmd進行兩遍掃描,如果第一遍掃描後,cmd是個普通的指令,則執行此指令,如果cmd中含
有變量,則第一遍掃描先确認變量的值,然後進行第二遍掃描,得出結果,例如:
# set -- arg1 arg2 ==>通過set設定兩個參數
# echo $# ==>$#表示傳參的個數
2
# echo \$$# ==>由于$#為2,是以此指令就變為echo $2 ,但此時并未輸出$2的值,而是輸出了$2,這也就是上述提到的提一次掃描,将$#替換為$2
$2
# eval "echo \$$#" ==>eval進行第2次掃描,直接輸出echo $2的值arg2
arg2
exec
指令格式:exec 指令參數
功能:exec指令能夠在不建立新的子程序的前提下,轉去執行指定的指令,當指定的指令執行完畢後,該程序也就
終止了,如果是遠端連接配接的會話,則執行完指令後,該會話直接退出。
如下:
[root@wtf ~]# exec date
2018年 10月 18日 星期四 14:32:19 CST
Connection to 192.168.246.171 closed.
➜ ~
另外,當使用exec打開檔案後,read指令每次都會将檔案指針移動到檔案的下一行進行讀取,直至檔案末尾,
利用這個可以實作處理檔案内容。
例如:
# seq 5 > /tmp/seq.txt
[root@wtf tmp]# cat test_seq.sh
#!/bin/bash
exec < /tmp/seq.txt
while read line
do
echo $line
done
echo "ok"
執行 test_seq.sh ,結果如下:
# sh test_seq.sh
1
2
3
4
5
ok
read
指令格式:read 變量名表
功能:從标準輸入讀取字元串等資訊,傳給shell程式内部定義的變量。
shift
用shift将位置參數移位(左移),将位置參數$1、$2等進行左移,即如果位置參數是$3、$2、$1,
那麼執行一次shift後,$3變為$2,$2變為$1,$1就消失了。
exit
shell程式,當然exit也可以選擇執行的數字作為傳回值。
shell變量子串知識
說明⚠️:
- 上述ID為11-14中表達式的冒号可以省略,如果省略了其中的冒号,則将每個定義中的“為空或未指派”部分改為“未指派”。
- 為了友善了解,這裡對${#parameter##word}舉例說明一下:
${#parameter%% a*c} :這裡的a*c表示比對的字元串,*表示比對所有,a*c表示比對開頭為a、中間為任意多字元,結尾為c的字元串。
有關上述比對删除的小結,總結如下:
有關上述替換比對的小結,總結如下:
變量的數值計算實踐
算術運算符
這裡重點說一下 ++ 和 —— ,因為有時候大家會對此有一定的誤解,看如下執行個體:
[root@www ~]# a=10 ==>定義變量a
[root@www ~]# echo $((a++)) ==>如果a在運算符++或--的前面,那麼輸出整個表達式時,會輸出a的值, 此前定義的變量a為10,是以此處的值為10.
10
[root@www ~]# echo $a ==>執行上述表達式後,因為有a++,是以a會自增1,是以輸出的值為11
11
[root@www ~]# a=11 ==>定義變量a
[root@www ~]# echo $((a--)) ==>如果a在運算符++或--的前面,那麼輸出整個表達式時,會輸出a的值,前定義的a為11,是以此處的值為11.
11
[root@www ~]# echo $a ==>執行上述表達式後,因為有a--,是以a會自減1,是以輸出的值為10
10
[root@www ~]# a=10
[root@www ~]# echo $((--a)) ==>如果a在運算符++或--的後面,那麼輸出整個表達式時,先進行自增或自減計算,因為a為10, 且要自減,是以表達式的值為9.
9
[root@www ~]# echo $a ==>執行上述表達式後,a自減1,是以表達式的值為9.
9
[root@www ~]# echo $((++a)) ==>如果a在運算符++或--的後面,那麼輸出整個表達式時,先進行自增或自減計算,因為a為9,且要自增1,是以表達式的值為10
10
[root@www ~]# echo $a ==>執行上述表達式後,a自增1,是以表達式的值為10
10
總結⚠️:
執行echo $((a++))和echo $((a--))指令輸出整個表達式時,輸出的值為a的值,表達式執行完畢後,會對a進行++、--的運算,而執行
echo $((++a))和echo $(--a)指令輸出整個表達式時,會先對a進行++、--的運算,然後再輸出表達式的值,即為a運算後的值。
記憶口訣⚠️:
變量a在運算符之前,輸出表達式的值為a,然後a自增或自減;
變量a在運算符之後,輸出的表達式會先進行自增或自減,表達式的值就是自增或自減後a的值。
常見的算術運算指令:
雙小括号"(())"數值運算指令
雙小括号"(())"數值運算的基礎文法
雙小括号"(())"的作用是進行數值運算與數值比較,效率很高,用法靈活,是企業場景運維人員經常采用的運算操作符。
操作方法見下表:
實戰--雙小括号
基礎運算
[root@wtf tmp]# echo $((1+1))
2
[root@wtf tmp]# echo $((8-3))
5
[root@wtf tmp]# echo $((2-3))
-1
[root@wtf tmp]# ((i=4)) 或 i=4
[root@wtf tmp]# ((i=i*3)) ## 擷取 i 值,然後計算 i*3 ,再指派給變量 i
[root@wtf tmp]# echo $i
12
綜合算術運算
[root@wtf tmp]# ((a=1+2**4-4%3))
[root@wtf tmp]# echo $a
16
[root@wtf tmp]# ((a=1+2**4-4%3))
[root@wtf tmp]# echo $a
16
[root@wtf tmp]# b=$((1+2**4-4%3))
[root@wtf tmp]# echo $b
16
特殊運算符号的運算
[root@wtf tmp]# a=7
[root@wtf tmp]# echo $((a=a+1))
8
[root@wtf tmp]# echo $((a+=1))
9
[root@wtf tmp]# echo $((a**2))
81
利用 “(())” 雙小括号進行判斷
[root@wtf tmp]# echo $((3<5)) ## 1 表示真
1
[root@wtf tmp]# echo $((3<1)) ## 0 表示假
0
通過 “(())” 運算後指派給變量
[root@wtf tmp]# myvar=100
[root@wtf tmp]# echo $((myvar+1))
101
或者:
[root@wtf tmp]# myvar=100
[root@wtf tmp]# myvar=$((myvar+1))
[root@wtf tmp]# echo $myvar
101
在 “(())” 中使用變量時可以去掉變量前的 $ 符号。
雙小括号 “(())” 在 Shell 腳本中的運用
[root@wtf tmp]# cat shuang_shell.sh
#!/bin/bash
## 這裡可以使用位置參數,使腳本具有更好的靈活性,如:
#a=$1
#b=$2
##那麼執行腳本時,要使用位置參數,如:
#sh shuang_shell.sh 3 4
a=6
b=2
echo "a-b=$((a-b))" ## 在 “(())” 中使用變量時可以去掉變量前的 $ 符号。
echo "a+b=$(($a+$b))"
[root@wtf tmp]# sh shuang_shell.sh
a-b=4
a+b=8
實戰--以上介紹的知識點
具體代碼如下:
#!/bin/bash
#add,subtract,multiply and divide by oldboy
print_usage(){
printf $"USAGE:$0 NUM1 {+|-|*|/} NUM2\n"
exit 1
}
if [ $# -ne 3 ];then
print_usage
fi
firstnum=$1
secondnum=$3
operators=$2
if [ -n "$(echo $firstnum|sed 's#[0-9]##g')" ];then
print_usage
fi
if [ "${operators}" != "+" ] && [ "${operators}" != "-" ] && [ "${operators}" != "*" ] && [ "${operators}" != "/" ];then
print_usage
exit 2
fi
if [ -n "$(echo $secondnum|sed 's#[0-9]##g')" ];then
print_usage
fi
echo "${firstnum}${operators}${secondnum}=$((${firstnum}${operators}${secondnum}))"
代碼執行結果如下:
[root@wtf tmp]# sh jisuanqi_v2.sh 1 + 2
1+2=3
[root@wtf tmp]# sh jisuanqi_v2.sh 3 \* 2 ## * 要轉義
3*2=6
[root@wtf tmp]# sh jisuanqi_v2.sh 4 / 2
4/2=2
[root@wtf tmp]# sh jisuanqi_v2.sh wutf / 2
USAGE:jisuanqi_v2.sh NUM1 {+|-|*|/} NUM2
[root@wtf tmp]# sh jisuanqi_v2.sh 4 / wutf
USAGE:jisuanqi_v2.sh NUM1 {+|-|*|/} NUM2
let運算指令的用法
let運算指令的文法格式:let 指派表達式
let指派表達式的功能等同于“((指派表達式))”
let指派:舉例:let i=i+2 ==>等同于((i=i+2)),後者的效率更高!
expr指令的用法
expr指令的基本用法:
expr既可以用于整數運算,也可以用于相關字元串長度、比對等的運算處理。
expr 用于計算
文法:expr Expression ==>expression中可包含變量
[root@wtf tmp]# expr 1 + 1
2
[root@wtf tmp]# expr 2 \* 3
6
在使用expr時,要注意以下2點
- 運算符及用于計算的數字左右都至少有一個空格,否則會報錯。
- 使用乘号時,必須用反斜線進行轉義。
expr 配合變量計算
expr 在 shell 中可配合變量進行計算,但需要用反引号或 $() 将計算表達式括起來,如:
[root@wtf tmp]# i=5
[root@wtf tmp]# i=$(expr $i + 5)
[root@wtf tmp]# echo $i
10
判斷變量或字元串是否為整數
原理:
利用以 expr 做計算時變量或字元串必須是整數的規則,把一個變量或字元串和一個已知的整數(非0)相加,看指令傳回的值是否為0。
如果是0,就認為做加法的變量或字元串為整數,否則就不是整數。
[root@wtf tmp]# i=7
[root@wtf tmp]# expr $i + 2 &> /dev/null ## &> /dev/null表示不保留任何輸出
[root@wtf tmp]# echo $? ## 表示傳回值
0
[root@wtf tmp]# expr $i + 2
9
[root@wtf tmp]# unset i
[root@wtf tmp]# i=wutf
[root@wtf tmp]# expr $i + 2 &> /dev/null
[root@wtf tmp]# echo $?
2
[root@wtf tmp]# expr $i + 2
expr: 非整數參數
通過傳參判斷輸出的内容是否為整數
# cat expr_test.sh
#!/bin/bash
expr $1 + 1 > /dev/null
[ $? -eq 0 ] && echo int || echo chars
執行上面的腳本,結果如下:
[root@wtf tmp]# sh expr_test.sh 1
int
[root@wtf tmp]# sh expr_test.sh wutf
expr: 非整數參數
chars
bc指令的用法
bc是Linux下的電腦,當然除了作為電腦使用,還可以作為指令行計算工具使用。
使用方法如下:
[root@wtf ~]# 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
3*3
9
[root@wtf ~]# echo 2+3|bc
5
[root@wtf ~]# echo "scale=2;9/2" | bc ==>使用scale=2保留2位小數
4.50
[root@wtf ~]# echo "scale=2;355/113" | bc
3.14
awk實作計算
利用awk運算的效果也很好,适合小數和整數,尤其是小數,運算很精确。
示例如下:
[root@wtf ~]# echo "5 6" | awk '{print ($1+$2)}' ==>$1為第1個數字,$2為第2個數字,用空格分開 ,注意awk '{ }'的單引号
11
[root@wtf ~]# echo "5.5 6.6" | awk '{print ($1+$2)}'
12.1
declare(同typeset)指令的文法
declare與typeset指令是bash的内置指令,二者指令的文法相同,用來聲明shell變量,設定變量的屬性。
常用指令參數:
- -r:設定變量為隻讀
- -i:設定變量為整數
- -a:設定變量為數組array
- -f:如果後面沒有參數的話,會列出之前腳本定義的所有函數,如果有參數的話,列出以參數命名的函數
- -x:設定變量在腳本外也可以使用
簡單使用如下:
[root@wtf ~]# declare -i A=1 B=2
[root@wtf ~]# A=A+B
[root@wtf ~]# echo $A
3
$[ ]符号的運算示例
[root@wtf ~]# echo $[1+2]
3
[root@wtf ~]# echo $[1*2]
2
基于shell變量輸入read指令的運算實踐
shell腳本除了可以直接指派或腳本傳參外,還可以使用read指令從标準輸入中獲得,read為bash的
内置指令,而已認證help read檢視幫助。
文法格式:read [參數] [變量名]
常用參數:
-p(prompt):設定提示資訊
# read -t 7 -p "Please input a number: " number
Please input a number: [root@wtf ~]#