手機版
你好,游客 登錄 注冊
背景:
閱讀新聞

Bash腳本編程之變量與多命令執行

[日期:2020-01-06] 來源:cnblogs.com/alongdidi  作者:阿龍弟弟 [字體: ]

變量基礎知識

程序由指令加數據所組成,而變量可以理解為數據來源的一種。

變量名可以理解為指向了某個內存空間的地址,對于變量的賦值可理解為向內存空間寫入數據,對于變量的引用可理解為從內存空間讀取數據。

變量有類型的概念(例如字符串、數字等),不同的類型決定了數據的存儲格式、可表示的數據范圍以及可參與的運算等。

在編程語言中,可以根據變量的強弱來劃分。例如C語言屬于強類型變量的語言,該類變量在類型不同的情況下無法直接進行運算。bash腳本則屬于弱類型變量的語言,不同類型的變量可以直接運算,默認將所有的變量統一視為字符型,必須在借助第三方工具的情況下才可以進行浮點數的運算,變量無需事先聲明即可使用(相當于把聲明、賦值和定義數據類型的操作同時實現)。

變量的聲明就是事先占用好這個內存空間。變量的強弱之分與是否需要事先聲明無關,例如Python是強變量類型的編程語言但是其變量不需要事先聲明。

變量名可由字母、數字和下劃線組成,并且不允許數字打頭(幾乎所有的編程語言均如此)。變量名要盡量做到見名知意,并且要有一定的規則,根據詞語來劃分(駝峰法、下劃線法等),例如:

my_favorite_sport="basketball"
myFavoriteSport="basketball"

不要使用bash保留字來給變量命名,例如if、else、then等。

變量根據作用域可以劃分為三種:

  • 本地變量:僅當前shell有效(即當前bash進程)。
  • 環境變量:當前shell及其子shell(即當前bash進程即其子bash進程)。
  • 局部變量:在某部分代碼片段中有效(例如函數)。

除了上述三種,還有位置參數變量和特殊變量:

  • 位置參數變量:用于傳參給shell腳本或者函數的變量,例如${1}、${2}等。
  • 特殊變量:在shell中具有特殊含義的變量,例如$?、$-等。

本地變量

本地變量的賦值與引用:

賦值:name=value
引用:${name}或者$name

在我們使用變量的時候,會遇到引號的情況,在bash中,引用(quoting)的作用是抑制bash對某些字符的特殊作用(例如美元符號$,就會做一些變量展開或者特殊符號的處理)。而引號則是引用的其中兩種方式(單引號和雙引號)。

單引號會使得其中的所有字符只有其字面意義,而雙引號只會抑制大部分的特殊字符含義,但是不包括$等其他一些字符。

[[email protected] ~]# name=zwl
[[email protected]-server ~]# echo '${name}'
${name}
[[email protected]-server ~]# echo "${name}"
zwl

在引用變量的時候,也建議使用${name},因為這樣子才可以支持bash的參數展開功能。

[[email protected] ~]# echo ${name}
alongdidi
[[email protected]-server ~]# echo ${name:2:3}
ong
[[email protected]-server ~]# echo $name:2:3
alongdidi:2:3

我們可以通過set(bash內置命令)來查看已經設置的變量名稱和值。不過set所顯示出來的變量非常多,還包含了環境變量和函數,因此一般需要通過管道傳輸給less分頁或者grep過濾。

~]# set | grep "^name"
name=alongdidi

set還可以用于設置shell的屬性(即工作特性)和位置參數,這里不展開。

當某個變量我們不要的時候,可以使用unset來將其取消掉。

[[email protected] ~]# unset name
[[email protected]-server ~]# echo $name

[[email protected]-server ~]# set | grep "^name"
[[email protected]-server ~]#

unset命令可以取消變量,也可以取消函數。

unset [-f] [-v] [name ...]

-f:指明取消的name是函數。

-v:指明取消的name是變量。

這兩個選項都可以省略,unset會首先嘗試取消一個變量,若失敗則再次嘗試取消一個函數。某些變量無法被unset,例如只讀變量。

可以通過shell內置命令readonly來將shell變量或者函數設置為只讀的屬性。

readonly [-aAf] [name[=value] ...]
readonly -p

第一種語法,是設置一個變量為只讀變量并且可以選擇是否賦值,如果此時不賦值,那么設置為只讀后就無法再賦值或者改值了。

-a:指明name為索引數組(indexed array)。

-A:指明name為關聯數組(associative array)。

-f:指明name為函數(function)。

[[email protected] ~]# readonly age=28
[[email protected]-server ~]# age=30
-bash: age: readonly variable
[[email protected]-server ~]# unset age
-bash: unset: age: cannot unset: readonly variable

-p:單獨使用,顯示出所有的只讀變量和函數。

[[email protected] ~]# readonly -p
declare -r BASHOPTS="checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath"
declare -ir BASHPID
declare -r BASH_COMPLETION_COMPAT_DIR="/etc/bash_completion.d"
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-RedHat-linux-gnu")'
declare -ir EUID="0"
declare -ir PPID="3530"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="0"
declare -r age="28"

注意:declare -r就表示定義一個只讀變量,這也是個shell內置命令,后面會提到。

我們剛說了,本地變量的作用域只在當前的shell中,那么在子shell和其他shell中應該是不存在的,我們來證明一下。

[[email protected] ~]# pstree -ph 1148
sshd(1148)┬─sshd(1851)───bash(1857)
           ├─sshd(3530)───bash(3536)───pstree(4859)
           └─sshd(4125)───bash(4131)
[[email protected]-server ~]# name=alongdidi
[[email protected]-server ~]# echo $name
alongdidi
[[email protected]-server ~]# bash
[[email protected]-server ~]# pstree -ph 1148
sshd(1148)─┬─sshd(1851)───bash(1857)
           ├─sshd(3530)───bash(3536)───bash(4861)───pstree(4894)
           └─sshd(4125)───bash(4131)
[[email protected]-server ~]# echo $name

[[email protected]-server ~]#

我們原本在PID為3536的shell(bash進程)中,在當前shell設置了變量name并且可獲取其值,隨后使用bash命令進入了子shell(PID為4861的bash進程)中再獲取這個變量,就獲取不到了。

如果我們使用exit命令退回剛才的??shell,就又可以獲取到該值。

[[email protected] ~]# exit
exit
[[email protected]-server ~]# echo $name
alongdidi

我們切換使用Xshell再創建了一個新的session,在那個session下嘗試獲取該變量的值,也是沒有的。證明成功。

[[email protected] ~]# pstree -ph 1148
sshd(1148)─┬─sshd(1851)───bash(1857)
           ├─sshd(3530)───bash(3536)
           └─sshd(4125)───bash(4131)───pstree(4860)
[[email protected]-server ~]# echo $name

[[email protected]-server ~]#

本地變量的生命周期,從創建的時候開始,直到所在的bash進程結束(比如使用exit)或者變量被unset。

環境變量

環境變量的作用域是當前shell及其子shell。因此也可以理解為將變量輸出(export)到了子shell中。無論子shell的層數有幾層,只要變量具備環境變量的屬性,那么它就都會有值。

可以通過export或者declare將變量設置為環境變量。

[[email protected] ~]# export name
[[email protected]-server ~]# bash
[[email protected]-server ~]# echo $name
alongdidi
[[email protected]-server ~]# bash
[[email protected]-server ~]# echo $name
alongdidi
[[email protected]-server ~]# bash 
[[email protected]-server ~]# echo $name
alongdidi

export的語法如下。

export [-fn] [name[=value] ...]
export -p

-f:聲明name是一個函數。

-n:去除環境變量的屬性。

-p:使用該選項或者僅使用export命令的話,可以查看當前所有的環境變量。declare -x有同效。外部命令env和printenv也可以實現。

export是專門用于設置與環境變量屬性相關的命令。declare是設置所有與變量相關的屬性(只讀、環境變量、整型、索引數組、關聯數組)等等。

多命令執行

;:分號,命令按順序執行,執行完第一個再執行第二個,后一個命令的執行與否與前一個命令的執行成功與否無關。

~]# COMMAND1; COMMAND2

&&:邏輯與,只有當COMMAND1執行成功的時候,才執行COMMAND2。類似于邏輯與運算,a && b,當a為1的時候(執行成功)還需要看b的值(即還需要執行b)才能決定整個表達式的值,如果a為0了,那么整個表達式必然為0,就不需要看b的值了(b就可以不執行),這也叫短路法則。

~]# COMMAND1 && COMMAND2

||:邏輯或,只有當COMMAND1執行失敗的時候,才執行COMMAND2。

~]# COMMAND1 || COMMAND2
linux
本文評論   查看全部評論 (0)
表情: 表情 姓名: 字數

       

評論聲明
  • 尊重網上道德,遵守中華人民共和國的各項有關法律法規
  • 承擔一切因您的行為而直接或間接導致的民事或刑事法律責任
  • 本站管理人員有權保留或刪除其管轄留言中的任意內容
  • 本站有權在網站內轉載或引用您的評論
  • 參與本評論即表明您已經閱讀并接受上述條款
海口彩票论坛