老男孩shell實戰讀書筆記(1-5章節)

老男孩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中的特殊位置參數變量,請見下表

老男孩shell實戰讀書筆記(1-5章節)

關於特殊位置參數實戰

使用條件表達式判斷語句

# 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指定的字符串及變量等顯示到標準輸出。

常見參數如下:

老男孩shell實戰讀書筆記(1-5章節)

實戰--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變量子串知識

老男孩shell實戰讀書筆記(1-5章節)

說明⚠️:

  • 上述ID爲11-14中表達式的冒號可以省略,如果省略了其中的冒號,則將每個定義中的“爲空或未賦值”部分改爲“未賦值”。
  • 爲了方便理解,這裏對${#parameter##word}舉例說明一下:
${#parameter%%  a*c} :這裏的a*c表示匹配的字符串,*表示匹配所有,a*c表示匹配開頭爲a、中間爲任意多字符,結尾爲c的字符串。

有關上述匹配刪除的小結,總結如下:

老男孩shell實戰讀書筆記(1-5章節)

有關上述替換匹配的小結,總結如下:

老男孩shell實戰讀書筆記(1-5章節)

變量的數值計算實踐

算術運算符

老男孩shell實戰讀書筆記(1-5章節)

這裏重點說一下 ++ 和 —— ,因爲有時候大家會對此有一定的誤解,看如下實例:

[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的值。

常見的算術運算命令:

老男孩shell實戰讀書筆記(1-5章節)

雙小括號"(())"數值運算命令

雙小括號"(())"數值運算的基礎語法

雙小括號"(())"的作用是進行數值運算與數值比較,效率很高,用法靈活,是企業場景運維人員經常採用的運算操作符。

操作方法見下表:

老男孩shell實戰讀書筆記(1-5章節)

實戰--雙小括號

基礎運算

[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):設置提示信息

-t(timeout):設置輸入等待時間,單位默認爲秒。

實例如下:

# read -t 7 -p "Please input a number: " number
Please input a number: [root@wtf ~]#

寫在最後

喜歡讀技術書籍,喜歡做讀書筆記,以上爲本人在讀《跟老男孩學Linux運維之shell編程實戰》這本書時的筆記,如有任何版權問題,請聯繫留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章