1. 程式人生 > >[Linux]shell基礎教程4-變數詳細講解

[Linux]shell基礎教程4-變數詳細講解



原創文章,歡迎轉載。轉載請註明:轉載自 祥的部落格
原文連結:https://blog.csdn.net/humanking7/article/details/84641588


文章目錄

環境

  • ubuntu 16.04
  • GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

1. 概述

變數可分為兩類:環境變數(全域性變數)

普通變數(區域性變數)

  • 環境變數也可稱為全域性變數,可以在建立它們的Shell及其派生出來的任意子程序Shell中使用,環境變數又可分為自定義環境變數bash內建的環境變數
  • 普通變數也可稱為區域性變數,只能在建立它們的Shell函式Shell指令碼 中使用。普通變數 一般由開發者在開發指令碼程式時建立。

預設情況下,在bash Shell中是 不會區分變數型別 的,例如常見的變數型別為整數字串等。這和其他強型別語言(比如C語言等)是有區別的。當然,如果需要指定Shell變數的型別,也可以使用declare -p顯示定義變數的型別,但在一般情況下沒有這個需求。

[email protected]:~# echo $HOME
/root
[email protected]:~# declare -p HOME 
declare -x HOME="/root"

2. 環境變數

環境變數一般是指用export內建命令匯出的變數(執行export -p可以檢視)。

所有的環境變數都是系統全域性變數,可用於所有子程序中,這包括編輯器Shell指令碼各類應用

環境變數可以在命令列中設定和建立,但使用者退出命令列時這些變數值就會丟失,如果希望 永久儲存 環境變數,可在使用者 家目錄 下的.bash_profile.bashrc非使用者登入模式特有,如遠端SSH)檔案中,或者全域性配置/etc/bashrc非使用者登入模式特有,如遠端SSH)或 /etc/profile 檔案中定義。在將環境變數放入上述的檔案中後,每次使用者登入時這些變數都將被初始化

按照系統規範,所有環境變數的名字均採用大寫形式 。在將環境變數應用於使用者程序程式之前,都應該用export命令匯出定義。

有一些環境變數,比如HOMEPATHSHELLUIDUSER等,在使用者登入之前就已經被/bin/login程式設定好了。通常環境變數被定義並儲存在使用者家目錄下的.bash_profile檔案或全域性的配置檔案/etc/profile中。

# 定義一個環境變數 MY_BLOG
[email protected]:~# export MY_BLOG="http://blog.csdn.net/humanking7/"

# 顯示環境變數(中間刪去了一些顯示內容)
[email protected]vultr:~# export -p
declare -x MY_BLOG="http://blog.csdn.net/humanking7/"
declare -x HOME="/root"
declare -x LANG="en_US.UTF-8"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LOGNAME="root"
declare -x MAIL="/var/mail/root"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
declare -x PWD="/root"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_TTY="/dev/pts/2"
declare -x TERM="xterm"
declare -x USER="root"
declare -x XDG_DATA_DIRS="/usr/local/share:/usr/share:/var/lib/snapd/desktop"

2.1. 與環境變數相關的命令

5個命令都與變數有關

  • set
  • unset
  • env
  • declare
  • export
  • readonly

set 命令會輸出所有的變數全域性變數區域性變數),直接在shell中輸入set,會有很多的資料輸出,建議用set | less進行檢視,使用set | wc -l可以發現一共有2106行資料,而且本身set命令也有很多選項和玩法,以後在慢慢研究。其中set -o會顯示bash shell的所有引數配置資訊。

env命令只會顯示全域性變數

declare命令會輸出所有的變數函式整數已經匯出的變數。用declare | wc -l一查還是2106行,declare本身是可以宣告、取消、檢視變數型別的,也有很多玩法。

export命令,對於檢視shell賦予程式的環境變數,我是特別喜歡用export -p進行顯示,非常清爽。

readonly 變數名,將設定變數為只讀變數,出於安全的原故,只讀變數是不可以復位/取消的,只有等到shell登出。

unset命令可以清除環境變數,而且setenvexport設定的變數,都可以用它來清除。

# 設定環境變數
[email protected]:~# export MY_BLOG="http://blog.csdn.net/humanking7/"
[email protected]:~# env | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
[email protected]:~# set | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
[email protected]:~# export -p | grep MY_BLOG
declare -x MY_BLOG="http://blog.csdn.net/humanking7/"
[email protected]:~# declare | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/

# 將變數設定為只讀
[email protected]:~# readonly MY_BLOG 

# 只讀變數無法改變和刪除
[email protected]:~# export MY_BLOG="csdn"
-bash: MY_BLOG: readonly variable
[email protected]:~# unset MY_BLOG 
-bash: unset: MY_BLOG: cannot unset: readonly variable

# 設定一個環境變數,然後清除
[email protected]:~# export WEB_SITE=google.com
[email protected]:~# env | grep WEB_SITE
WEB_SITE=google.com
[email protected]:~# unset WEB_SITE 
[email protected]:~# env | grep WEB_SITE
[email protected]:~# 

2.2. 自定義環境變數

# 方法1
export variableName=value

# 方法2
declare -x variableName=value

上述的兩個方法也是重新賦值的方法,示例如下:

[email protected]:~# export MY_NAME=Q
[email protected]:~# env | grep MY_NAME
MY_NAME=Q
[email protected]:~# declare -x MY_NAME=F
[email protected]:~# env | grep MY_NAME
MY_NAME=F
[email protected]:~# export MY_NAME=A
[email protected]:~# env | grep MY_NAME
MY_NAME=A

2.3. 讓環境變數永久生效

如果希望環境變數永久生效,則可以將 環境變數 放在使用者環境變數檔案全域性環境變數檔案裡。

讓環境變數永久生效的常用設定檔案

2.3.1. 使用者環境變數配置

家目錄(比如說家目錄是/root/)下的兩個檔案中寫入環境變數(隨便一個就可以)

/root/.bashrc
/root/.bash_profile

2.3.2. 全域性環境變數配置

常見的全域性環境變數的配置檔案如下:

/etc/bashrc      # 推薦在此檔案中優先設定
/etc/profile
/etc/profile.d/

2.4. 啟動順序

Shell初始化過程是這樣的:

  1. bash 檢查檔案/etc/profile(預設的Shell主環境變數檔案,每個使用者登入都會載入)是否存在,存在就讀取環境變數,否則跳過;
  2. 當載入完/etc/profile檔案後,才會執行/etc/profile.d/目錄下的指令碼檔案,這個目錄下的指令碼檔案有很多
  3. 之後bash 檢查家目錄$HOME下的檔案.bash_profile (使用者環境變數檔案)是否存在,存在就讀取環境變數,否則跳過;
  4. 又會去找$HOME/.bashrc(使用者環境變數檔案),存在就讀取環境變數,否則跳過。
  5. $HOME/.bashrc檔案中又會去找/etc/bashrc(全域性環境變數檔案),存在就讀取環境變數,否則跳過。

注意:
如果使用者的Shell不是登入時啟動的(比如手動敲下bash時啟動 或者 其他不需要輸入密碼的登入遠端SSH連線情況),那麼這種非登入Shell只會載入$HOME/.bashrc(使用者環境變數檔案),並會去找/etc/bashrc(全域性環境變數檔案)。因此如果希望在非登入Shell下也可讀到設定的環境變數等內容,就需要將變數設定等寫入$HOME/.bashrc或者/etc/bashrc,而不是$HOME/.bash_profile/etc/profile

2.5. 小結

環境變數的知識(見參考文獻1 ):

  1. 變數名通常要大寫。
  2. 變數可以在自身的Shell及子Shell中使用。
  3. 常用export來定義環境變數
  4. 執行env預設可以顯示所有的環境變數名稱對應的值
  5. 輸出時用“$變數名”,取消時用“unset變數名”
  6. 書寫crond定時任務時要注意,指令碼要用到的環境變數最好先在所執行的Shell指令碼中重新定義。
  7. 如果希望環境變數永久生效,則可以將其放在使用者環境變數檔案全域性環境變數檔案裡。

3. 普通變數

3.1. 定義

本地變數在使用者當前Shell生存期的指令碼中使用。如果在Shell中啟動另一個程序退出,那麼變數將會失效。

3種定義方法:

# 賦值時不加引號
variableName=value 

# 賦值時加單引號
variableName='value'       

# 賦值時加雙引號
variableName="value"       

變數的內容可以用單引號雙引號引起來,也可不加引號,但是這三者的含義是不同的。

3.2. 輸出及其顯示

$變數名表示輸出變數,可以用$變數名${變數名}兩種用法。

3.2.1. 例子1

#!/bin/bash
# author:Q
# url:http://blog.csdn.net/humanking7/

var1=2018
var2='2018'
var3="2018"

echo "var1=$var1"
echo "var2=$var2"
echo "var3=${var3}"

執行結果:

[email protected]:~# ./t2.sh 
var1=2018
var2=2018
var3=2018

3.2.2. 例子2

#!/bin/bash
# author:Q
# url:http://blog.csdn.net/humanking7/

var1=2018
var1=2018-$var1
var2='2018-$var1'
var3="2018-$var1"

echo "var1=$var1"
echo "var2=$var2"
echo "var3=${var3}"

執行結果:

[email protected]:~# ./t2.sh 
var1=2018-2008
var2=2018-$var1
var3=2018-2018-2008

分析:
1種定義方式,var1,是不加任何引號直接定義變數的內容(值)。當內容簡單連續的數字字串路徑名時,可以這樣用。不加引號時,裡有變數會被解析後再輸出,上述變數定義中因為$var1的值被解析為2018,因此新的var1值就是2018-2018

2種定義方式,通過單引號定義。這種定義方式的特點就是,單引號裡面是什麼,輸出內容就是什麼,即使內容(值)裡面有變數或者命令(命令需要反引號引起來)。所以對var2定義是2018-$var1,最終也是原樣輸出。

3種定義方式,通過雙引號定義。這種定義方式的特點是,輸出變數內容時引號裡的變數及命令會經過解析後再輸出內容。這種方式比較適合於字串中附帶有變數命令且想將其解析後再輸出的變數定義。

Tip:

  1. 數字內容的變數定義可以不加引號
  2. 其他沒有特別要求的字串等定義最好都加上雙引號
  3. 如果真的需要原樣輸出就加單引號

3.3. 把命令的結果作為變數的內容賦值的方法

對需要獲取命令結果的變數內容賦值的常見方法有2種:

# 方法1
# 把命令用反引號引起來,不推薦使用這種方法,因為容易和單引號混淆
variableName=`ls`

# 方法2
# 把命令用$()括起來,推薦使用這種方法
variableName=$(ls)

方法1:

[email protected]:~# ls -1
code
control_vpn
restart_ss.sh
showUsed_ss.sh
t2.sh
[email protected]:~# cmd=`ls -1`
[email protected]:~# printf "$cmd"
code
control_vpn
restart_ss.sh
showUsed_ss.sh

方法2:

[email protected]:~# cmd2=$(ls -1)
[email protected]:~# printf "$cmd2"
code
control_vpn
restart_ss.sh
showUsed_ss.sh

3.4. 注意

單獨拎出來寫一個小節,覺得是這個有點重要。

變數名前加$可以取得該變數的值,使用echoprintf命令可以顯示變數的值$變數名${變數名} 的寫法不同,但效果是一樣的。

變數後面連線有其他字元的時候,必須給變數加上大括號{},如下面的例子:

[email protected]:~# var1='my '
[email protected]:~# var1name=csdn

[email protected]:~# echo $var1name
csdn
[email protected]:~# echo ${var1}name
my name

Tip:

  1. 數字內容的變數定義可以不加引號
  2. 其他沒有特別要求的字串等定義最好都加上雙引號
  3. 如果真的需要原樣輸出就加單引號
  4. 希望變數值引用命令並獲取命令的結果時就用反引號$()

4. 例子

例子1:

[email protected]:~# echo "today : `date`"
today : Thu Nov 29 14:07:43 UTC 2018

[email protected]:~# echo "today : $(date)"
today : Thu Nov 29 14:07:57 UTC 2018

例子2:

# test.txt 檔案裡面有6行內容
# 其中有2行包含變數var1的值"csdn"
# 其中有2行包含"$var1",這個字串
[email protected]:~# cat test.txt 
csdn
https://blog.csdn.net/humanking7/
baidu.com
google.com
$var1
$var1name

# 定義一個變數
[email protected]:~# var1=csdn

# 查詢變數"值" 與 檔案匹配的內容
[email protected]:~# grep $var1 test.txt 
csdn
https://blog.csdn.net/humanking7/

[email protected]:~# grep ${var1} test.txt 
csdn
https://blog.csdn.net/humanking7/

[email protected]:~# grep "$var1" test.txt 
csdn
https://blog.csdn.net/humanking7/

# 查詢字串"$var1" 與 檔案匹配的內容
[email protected]:~# grep '$var1' test.txt 
$var1
$var1name

參考文獻1

5. 參考文獻:

  1. 跟老男孩學運維:Shell程式設計實戰

OK!
以上,Enjoy~


讚賞碼New