1. 程式人生 > >Linux之bash變數和邏輯運算

Linux之bash變數和邏輯運算

什麼是變數?

變數最初來源於數學,指的是非固定的值可變化的數通常用拉丁字母表示。在計算機中變數它依舊指的是可變化的數,只不過表現形式有些變化。它指的是變數名+所指向的記憶體空間

變數的特點

變數分強型別變數,與弱型別變數

強型別變數:變數需事先宣告且需提前定義其變數儲存格式

弱型別變數:不需事先宣告,不需定義變數儲存格式。

bash把所有變數統統視作字元型;bash中的變數無需事先宣告,相當於,把宣告和賦值過程同時實現。

 

變數名的命名規範

變數名只能包含數字字母下劃線,而且不能以數字開頭

其命名要求見名知義,命名機制遵循某種法則(駝峰法則)

不能使用程式的保留字:if,else,then,while,for...


 

bash的變數型別及其使用格式

本地變數,環境變數,區域性變數,位置引數變數,特殊變數

變數引用格式:$VAR、${VAR}

………………………………………………………………………………………………………………………

本地變數:作用域僅為當前shell程序

變數賦值:name=‘value’

value有如下引用型別

 

1、直接字串引用,格式name="CHARS"

1

2

3

[[email protected]

 ~]# name1=abc

[[email protected] ~]# echo $name1 

abc

2、變數引用,格式:name=“$VAR”

1

2

3

[[email protected] ~]# name2=$SHELL

[[email protected] ~]# echo $name2

/bin/bash

3、命令引用,格式:name=`COMMAND` | name=$(COMMAND)

1

2

3

4

5

6

[[email protected] ~]# name3=`date`

[[email protected] ~]# echo $name3

2016年 08月 14日 星期日 11:16:55 CST

[[email protected] ~]# name3=$(date)

[[email protected] ~]# echo $name3

2016年 08月 14日 星期日 11:17:11 CST

“”:弱引用,其中的變數引用會被替換為變數值;

1

2

3

[[email protected] ~]# name4="$name1"

[[email protected] ~]# echo $name4

abc

‘’:強引用,其中的變數引用不會被替換為變數值,而保持原字串;

1

2

3

[[email protected] ~]# name5='$name1'

[[email protected] ~]# echo $name5

$name1

命令set用於顯示已定義的所有變數

撤銷已定義的變數,格式:unset 變數名

1

2

3

4

5

[[email protected] ~]# echo $name5

$name1

[[email protected] ~]# unset name5

[[email protected] ~]# echo $name5

[[email protected] ~]#

在剛接觸bash變數時特別容易搞錯的就是變數的使用格式,有時候該命令引用卻忘記加``或$(),還有就是強引用與弱引用的使用時機。

 

下面以例子說明本地變數的作用範圍,使用命令bash進入子shell

1

2

3

4

5

6

7

[[email protected] ~]# bash

[[email protected] ~]# echo $name1

  

[[email protected] ~]# exit

exit

[[email protected] ~]# echo $name1

abc

由實驗可知,作用域僅為當前shell程序。當然上面實驗做的不夠完善,因為並沒有演示在符父shell中其變數是否有效,大家可以在下面補充實驗去驗證。

………………………………………………………………………………………………………………………

環境變數:作用域為當前shell程序及子程序

變數賦值:

有四種賦值格式:

    1、export name=value

    2、name=value

       export name

    3、declare -x name=value

    4、name=value

       declare -x name

:bash內嵌了許多環境變數(通常全為大寫字元),用於定義bash的工作環境

檢視/顯示環境變數 命令

export

1

2

3

4

5

6

[[email protected] ~]# export | head -5

declare -x HISTCONTROL="ignoredups"

declare -x HISTSIZE="1000"

declare -x HOME="/root"

declare -x HOSTNAME="centos7"

declare -x LANG="zh_CN.UTF-8"

declare -x

1

2

3

4

5

6

[[email protected] ~]# export | head -5

declare -x HISTCONTROL="ignoredups"

declare -x HISTSIZE="1000"

declare -x HOME="/root"

declare -x HOSTNAME="centos7"

declare -x LANG="zh_CN.UTF-8"

 

printenv

1

2

3

4

5

6

[[email protected] ~]# printenv | head -5

XDG_SESSION_ID=8

HOSTNAME=centos7

SELINUX_ROLE_REQUESTED=

TERM=linux

SHELL=/bin/bash

env

1

2

3

4

5

6

[[email protected] ~]# printenv | head -5

XDG_SESSION_ID=8

HOSTNAME=centos7

SELINUX_ROLE_REQUESTED=

TERM=linux

SHELL=/bin/bash

上面四個命令雖然顯示順序略有不同但是所包含的內容都是一樣的

1

2

3

4

5

6

7

8

[[email protected] ~]# env | wc -l

24

[[email protected] ~]# printenv | wc -l

24

[[email protected] ~]# export | wc -l       

24

[[email protected] ~]# declare -x | wc -l     

24

撤銷環境變數

格式:unset VAR

下面通過例子驗證環境變數的作用範圍

1

2

3

4

5

6

[[email protected] ~]# export name6=$name2

[[email protected] ~]# echo $name6

/bin/bash

[[email protected] ~]# bash

[[email protected] ~]# echo $name6

/bin/bash

………………………………………………………………………………………………………………………

區域性變數:作用域僅為某程式碼片段(通常用在函式)

因為函式還沒學到,這裡不舉例子

………………………………………………………………………………………………………………………

位置變數:當執行指令碼的shell程序傳遞的引數

$1,$2,...$(10)...:對應呼叫第1,第2...第10個引數

………………………………………………………………………………………………………………………

特殊變數:shell內建的特殊功用的變數

$#:傳遞給指令碼引數的個數

$*:傳遞給指令碼的所有引數;各引數讀成多個獨立字串

[email protected]:傳遞給指令碼的所有引數;各引數讀成一個完整的字串形式

$?:程式執行狀態返回值,0表示正確,1-255表示失敗
$0:表示命令本身

算術運算

Linux中的運算子主要有單目運算子和雙目運算子,運算子也有優先順序的高低之分。

運算子主要有以下這些:

優先順序 運算子 型別 說明
13 +、- 單目 單目正、單目負。它們是單目運算子的正、負,而不是加、減。
12 !、~ 單目 邏輯非、按位取反或補碼。
11 *、/、% 雙目 乘、除、取模。
10 +、- 雙目 加、減。
9 <<、>> 雙目 按位左移、按位右移。
8 <、<=、>、>= 雙目 小於、小於等於、大於、大於等於。
7 ==、!= 雙目 等於、不等於。
6 & 雙目 按位與。
5 ^ 雙目 按位異或。
4 | 雙目 按位或。
3 && 雙目 邏輯與。
2 || 雙目 邏輯或。
1 =、+=、-=、*=、/=、%=、&=、^=、|=、<<=、>>= 雙目 賦值、運算且賦值。

說明:對於該表,數值越大,優先順序越高。故賦值運算子的優先順序最低。

注意: 小括號內的表示式的優先順序最高,會優先運算。因此,可以用小括號改變運算子的優先順序。

優先順序越高,會先進行運算;相同優先順序的運算子,按照先後順序順序運算。

--------------------- 本文來自 lamp_yang_3533 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/lamp_yang_3533/article/details/70041211?utm_source=copy

在未學習bash中的算術運算之前如果要計算從1+...+10需要使用管道將其送入bc計算器來解決,

echo {1..10} | tr ' ' '+'| bc很麻煩。而使用bash中的算術運算則可以簡化程式碼。

bash中的算術運算格式:有很多種,本文只介紹常用的4種

1)let VAR=算術運算表示式

1

2

3

[[email protected] test]# let sum1=1+10

[[email protected] test]# echo $sum1

11

2)VAR=$[算術表示式]

1

2

3

[[email protected] test]# sum2=$[2+2]

[[email protected] test]# echo $sum2

4

3)VAR=$((算術表示式))

1

2

3

[[email protected] test]# sum3=$((5+5))

[[email protected] test]# echo $sum3

10

4)VAR=$(expr $ARG $OP $ARG2)

1

2

3

4

5

6

[[email protected] ~]# sum4=$(expr 2+8)

[[email protected] ~]# echo $sum4

2+8

[[email protected] ~]# sum4=$(expr 2 + 8 )

[[email protected] ~]# echo $sum4

10

這種是呼叫expr命令計算後面運算表示式,它要求數值與運算子之間有空格,沒有空格則不進行計算,保持運算表示式原本模樣賦值給變數。

 

:它與上述三種不同之處還有如果有乘法運算,乘法符號*在第四種裡面需要加\進行轉義。

以下為四種算術運算在乘法中的表現

1

2

3

4

5

6

7

8

9

10

11

12

13

14

[[email protected] ~]# sum4=$(expr 2 * 8 )

expr: 語法錯誤

[[email protected] ~]# sum4=$(expr 2 \* 8 )

[[email protected] ~]# echo $sum4

16

[[email protected] ~]# let sum1=6*6

[[email protected] ~]# echo $sum1

36

[[email protected] ~]# sum2=$[2*3]

[[email protected] ~]# echo $sum2

6

[[email protected] ~]# sum3=$((3*4))

[[email protected] ~]# echo $sum3

12

第四種需要轉義,其他三種不需要。

邏輯運算子

邏輯卷標 表示意思
1. 關於檔案與目錄的偵測邏輯卷標!
-f 常用!偵測『檔案』是否存在 eg: if [ -f filename ]
-d 常用!偵測『目錄』是否存在
-b 偵測是否為一個『 block 檔案』
-c 偵測是否為一個『 character 檔案』
-S 偵測是否為一個『 socket 標籤檔案』
-L 偵測是否為一個『 symbolic link 的檔案』
-e 偵測『某個東西』是否存在!
2. 關於程式的邏輯卷標!
-G 偵測是否由 GID 所執行的程式所擁有
-O 偵測是否由 UID 所執行的程式所擁有
-p 偵測是否為程式間傳送資訊的 name pipe 或是 FIFO (老實說,這個不太懂!)
3. 關於檔案的屬性偵測!
-r 偵測是否為可讀的屬性
-w 偵測是否為可以寫入的屬性
-x 偵測是否為可執行的屬性
-s 偵測是否為『非空白檔案』
-u 偵測是否具有『 SUID 』的屬性
-g 偵測是否具有『 SGID 』的屬性
-k 偵測是否具有『 sticky bit 』的屬性
4. 兩個檔案之間的判斷與比較 ;例如[ test file1 -nt file2 ]
-nt 第一個檔案比第二個檔案新
-ot 第一個檔案比第二個檔案舊
-ef 第一個檔案與第二個檔案為同一個檔案( link 之類的檔案)
5. 邏輯的『和(and)』『或(or)』
&& 邏輯的 AND 的意思
|| 邏輯的 OR 的意思

  

邏輯表示式

 

  • test 命令

使用方法:test EXPRESSION

如:

[[email protected] ~]# test 1 = 1 && echo 'ok'
ok

[[email protected] ~]# test -d /etc/ && echo 'ok' 
ok

[[email protected] ~]# test 1 -eq 1 && echo 'ok'
ok

 

[[email protected] ~]# if test 1 = 1 ; then echo 'ok'; fi
ok

 

注意:所有字元 與邏輯運算子直接用“空格”分開,不能連到一起。

 

  • 精簡表示式
  • [] 表示式

[[email protected] ~]# [ 1 -eq 1 ] && echo 'ok'           
ok

[[email protected] ~]# [ 2 < 1 ] && echo 'ok'                  
-bash: 2: No such file or directory

 

[[email protected] ~]# [ 2 \< 1 ] && echo 'ok'

[[email protected] ~]# [ 2 -gt 1 -a 3 -lt 4 ] && echo 'ok'

ok    

[[email protected] ~]# [ 2 -gt 1 && 3 -lt 4 ] && echo 'ok'   
-bash: [: missing `]'

注意:在[] 表示式中,常見的>,<需要加轉義字元,表示字串大小比較,以acill碼 位置作為比較。 不直接支援<>運算子,還有邏輯運算子|| && 它需要用-a[and] –o[or]表示

 

 

 

  • [[]] 表示式
[[email protected] ~]# [ 1 -eq 1 ] && echo 'ok'           
ok

[[email protected] ~]$ [[ 2 < 3 ]] && echo 'ok' 
ok

[[email protected] ~]$ [[ 2 < 3 && 4 > 5 ]] && echo 'ok' 
ok

注意:[[]] 運算子只是[]運算子的擴充。能夠支援<,>符號運算不需要轉義符,它還是以字串比較大小。裡面支援邏輯運算子:|| &&

 

 

三、效能比較

bash的條件表示式中有三個幾乎等效的符號和命令:test,[]和[[]]。通常,大家習慣用if [];then這樣的形式。而[[]]的出現,根據ABS所說,是為了相容><之類的運算子。以下是比較它們效能,發現[[]]是最快的。


$ time (for m in {1..100000}; do test -d .;done;)
real    0m0.658s
user    0m0.558s
sys     0m0.100s


$ time (for m in {1..100000}; do [ -d . ];done;)
real    0m0.609s
user    0m0.524s
sys     0m0.085s


$ time (for m in {1..100000}; do [[ -d . ]];done;)
real    0m0.311s
user    0m0.275s
sys     0m0.036s


不考慮對低版本bash和對sh的相容的情況下,用[[]]是相容性強,而且效能比較快,在做條件運算時候,可以使用該運算子。