bash 教程-4 shell 變數 算術表示式 [MD]
阿新 • • 發佈:2022-01-15
我的GitHub | 我的部落格 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | [email protected] |
目錄
目錄Bash 教程
本文改編自 網道的 Bash 教程,主要為了精簡大量本人不感興趣的內容。
Bash 變數
Bash 變數分成環境變數和自定義變數兩類。
- 環境變數是 Bash 環境自帶的變數,可以直接使用。通常是系統定義好的,也可以由使用者從父 Shell 傳入子 Shell。
- 自定義變數是使用者在當前 Shell 裡面自己定義的變數,僅在當前 Shell 可用。
set # 顯示所有變數(包括環境變數和自定義變數),以及所有的 Bash 函式
環境變數
很多環境變數很少發生變化,而且是隻讀的,可以視為常量。
由於環境變數的變數名全部都是大寫,所以傳統上,如果使用者要自己定義一個
常量
,也會使用全部大寫的變數名。
env # 【printenv】,顯示所有環境變數 echo $PATH # 【printenv PATH】,檢視單個環境變數的值 echo -e ${PATH//:/"\n"} # 將環境變數 PATH 中的所有分隔符,由【:】替換成【\n】,並解釋為換行符 echo -e "$BASHPID \n$BASHOPTS \n$DISPLAY \n$EDITOR \n$HOME \n$HOST \n$IFS \n$LANG" echo -e "$PS1 \n$PS2 \n$PWD \n$RANDOM \n$SHELL \n$SHELLOPTS \n$TERM \n$UID \n$USER"
常見的環境變數。
BASHPID
:【104】Bash 程序的程序 IDBASHOPTS
:當前 Shell 的引數,可以用shopt
命令修改DISPLAY
:圖形環境的顯示器名字,通常是:0
,表示 X Server 的第一個顯示器EDITOR
:預設的文字編輯器HOME
:【/home/bqt】使用者的主目錄HOST
:當前主機的名稱。IFS
:詞與詞之間的分隔符,預設為空格LANG
:【C.UTF-8】字符集以及語言編碼,比如zh_CN.UTF-8
PATH
:由冒號分開的目錄列表,當輸入可執行程式名後,會搜尋這個目錄列表PS1
:Shell 提示符PS2
:【>】輸入多行命令時,次要的 Shell 提示符PWD
:【/home/bqt】當前工作目錄RANDOM
:【19211】返回一個0到32767之間的隨機數SHELL
:【/bin/bash】Shell 的名字SHELLOPTS
:啟動當前 Shell 的set
命令的引數TERM
:【xterm-256color】終端型別名,即終端模擬器所用的協議UID
:【1000】當前使用者的 ID 編號USER
:【bqt】當前使用者的使用者名稱
定義變數
- 變數名的規則和 Java 等程式語言一樣
- 變數名區分大小寫
- Bash 沒有資料型別的概念,所有的變數值都是字串
- 注意,變數名和等號之間不能有空格
var=value # 變數名區分大小寫,變數值都是字串
b="b qt" # 如果變數值包含空格,必須放在引號裡面
e=$(pwd) # 【e=`pwd`】變數值可以是命令的執行結果
f=$((5*7)) # 變數值可以是數學運算的結果
foo=1;bar=2 # 同一行定義多個變數,必須使用分號分隔
for file in $(ls $(pwd)); do echo $file; done
讀取變數
- 如果變數不存在,會輸出空字元,而不會報錯
- 在變數名與其他字元連用的情況下,必須使用 花括號 包圍的格式:
${var}
- 如果變數的值本身也是變數,必須在變數前面加 感嘆號 才能讀取最終的值:
${!var}
- 變數值包含連續空格、製表符、換行符時,直接讀取時會被合併成一個空格;放在 雙引號 裡面能保持原來的格式
echo $100.00 # 【00.00】Bash 將【$1】解釋成了變數,該變數不存在,會輸出空字元
echo \$100.00 # 【$100.00】加反斜槓進行轉義
bqt=baiqiantao
echo $bqt2022 # 【(空)】Bash 將其整個 bqt2022 解釋為變數,而這個變數是不存在的
echo ${bqt}2022 # 【baiqiantao2022】在變數名與其他字元連用的情況下,必須使用花括號包圍
var=USER
echo $var # 【USER】
echo ${!var} # 【bqt】如果變數的值本身也是變數,必須使用【${!var}】讀取最終的值
a="1 2 3"
echo $a # 【1 2 3】直接讀取時,Shell 會將連續空格合併成一個
echo "$a" # 【1 2 3】放在雙引號裡面讀取時,能保持原來的格式
刪除變數
unset
命令用來刪除一個變數,這個命令等價於將變數設成空字串。
這個命令不是很有用,因為不存在的 Bash 變數一律等於空字串,所以即使用
unset
命令刪除了變數,還是可以讀取這個變數,值為空字串。
# 以下三種方式效果是一樣的
unset bqt
bqt=''
bqt=
特殊變數 & 傳遞引數
Bash 提供一些特殊變數。這些變數的值由 Shell 提供,使用者不能進行賦值。
$0
:當前 Shell 的名稱(在命令列直接執行時),或者指令碼檔名(在指令碼中執行時)$n
:傳遞到指令碼的第 n 個引數的值,建議使用${n}
來獲取$#
:傳遞到指令碼的引數數量$*
:顯示所有向指令碼或函式傳遞的引數,與$@
基本相同,區別見下文$@
:顯示所有向指令碼或函式傳遞的引數,與$*
基本相同,區別見下文$?
:上一個命令的退出碼,返回0
表示上一個命令執行成功;否則,表示上一個命令執行失敗$$
:當前 Shell 的程序 ID,常用來輔助命名臨時檔案$-
:當前 Shell 的啟動引數$_
:上一個命令的最後一個引數,不一定是使用者輸入的引數$!
:最近一個後臺執行的非同步命令的程序 ID,沒有的話返回空
# 呼叫格式【./test.sh 29 男】
chmod 777 test.sh
echo $0 #【./test.sh】指令碼檔名
echo $1 #【29】
echo $2 #【男】
echo $# #【2】傳遞到指令碼的引數數量
echo $* #【29 男】以一個字串顯示所有向指令碼或函式傳遞的引數
echo $@ #【29 男】
echo $? #【0】上一個命令的退出碼
echo $$ #【14372】當前 Shell 的程序 ID
echo $- #【hBH】當前 Shell 的啟動引數
echo $_ #【hBH】上一個命令的最後一個引數,不一定是使用者輸入的引數
echo $! #【】最近一個後臺執行的非同步命令的程序 ID
$*
與 $@
的區別:在雙引號
中,$*
的作用是將所有引數當做一個引數
# 【./test.sh 29 男 白乾濤】
for i in $@; do echo -n $i-; done; # 【29-男-白乾濤】
for i in $*; do echo -n $i-; done; # 【29-男-白乾濤】
for i in "$@"; do echo -n $i-; done; # 【29-男-白乾濤】
for i in "$*"; do echo -n $i-; done; # 【29 男 白乾濤】注意,這裡是將所有引數當做一個引數
for i in '$@'; do echo -n $i-; done; # 【$@】
for i in '$*'; do echo -n $i-; done; # 【$*】
變數未定義時的預設值
${var:-word}
:如果變數var
存在且不為空,則返回它的值,否則返回word
${var:=word}
:如果變數var
存在且不為空,則返回它的值,否則將它設為word
,並且返回word
${var:+word}
:如果變數var
存在且不為空,則返回word
,否則返回空值,可用來測試變數是否存在${var:?info}
:如果變數var
存在且不為空,則返回它的值,否則中斷指令碼的執行,並列印var: info
echo ${abc:-"變數未定義"} # 【變數未定義】
echo ${abc:="baiqiantao"} # 【baiqiantao】
echo ${bqt:+"變數已定義"} # 【變數已定義】
echo ${abc:?"變數未定義"} # 【bash: abc: 變數未定義】變數未定義時就中斷執行,並返回給定的報錯資訊
echo ${abc:?} # 【bash: abc: parameter null or not set】可以省略報錯資訊
上面四種語法如果用在指令碼中,變數名的部分可以用數字1
到9
,表示指令碼的引數。
宣告輸出變數 export
export
命令用來向子 Shell 輸出變數。- 使用者建立的變數僅可用於當前 Shell,使用
export
命令可以把變數傳遞給子 Shell - 通過
export
命令輸出的變數,對於子 Shell 來說就是環境變數 - 子 Shell 如果修改繼承的變數,不會影響父 Shell
bqt=baiqiantao
export bqt # 輸出變數 bqt,執行後,當前 Shell 及隨後新建的子 Shell,都可以讀取變數 bqt
export var=value # 給變數賦值並輸出
# 子 Shell 如果修改繼承的變數,不會影響父 Shell
bash # 新建子 Shell
echo $bqt # 讀取 $bqt
bqt=baz # 修改繼承的變數
exit # 退出子 Shell
echo $bqt # 讀取 $bqt
宣告只讀變數 readonly
宣告只讀變數,等同於 declare -r
,聲明後無法改變變數值,也不能 unset
變數
readonly
命令有三個引數
-f
:宣告的變數為函式名-p
:打印出所有的只讀變數-a
:宣告的變數為陣列
宣告時執行算術式 let
使用 let
命令宣告變數時,可以直接執行算術表示式。
let a=1+2 # 使用 let 命令宣告變數時,可以直接執行算術表示式
let "b =1 +2" # 引數表示式如果包含空格,需要使用引號
echo $a $b # 【3 3】
let "v1 = 1" v2=v1++ # 可以同時對多個變數賦值,賦值表示式之間使用空格分隔
echo $v1,$v2 # 【2,1】,v2=v1++ 的意思是:先返回 v1 的值,然後 v1 再自增
宣告特殊變數 declare
declare
命令可以宣告一些特殊型別的變數。declare
命令如果用在函式中,宣告的變數只在函式內部有效,等同於 local
命令。
- 宣告整數變數
-i
:聲明後可以直接進行數學運算 - 宣告只讀變數
-r
:等同於readonly
命令,聲明後無法改變變數值,也不能unset
變數 - 宣告大寫字母
-u
:聲明後可以自動把變數值轉成大寫字母 - 宣告小寫字母
-l
:聲明後可以自動把變數值轉成小寫字母 - 輸出變數資訊
-p
:輸出已定義變數的值,未定義的變數會提示找不到;不帶引數時輸出所有變數的資訊 - 輸出環境變數
-x
:等同於export
命令,可以將一個變數輸出為子 Shell 的環境變數 - 輸出所有函式名
-F
:不包含函式定義 - 輸出所有函式定義
-f
:包含函式定義 - 宣告陣列變數
-a
:
# 宣告整數變數
declare -i a=2 b=5 # 宣告整數變數,聲明後可以直接進行數學運算
declare -i c=a*b # 只要一個變數宣告為整數,它的賦值就會自動解釋為整數運算,這裡 a、b 可不宣告為整數變數
echo $a*$b=$c # 【2*5=10】
c=bqt; echo $c # 【0(不確定的值)】變數宣告為整數以後,如果被改寫為字串,不會報錯,但會賦以不確定的值
# 宣告只讀變數
declare -r r=1 # 宣告只讀變數,等同於 readonly 命令,聲明後無法改變變數值,也不能 unset 變數
r=2 # 【bash: r: readonly variable】報錯,命令執行失敗
unset r # 【bash: unset: r: cannot unset: readonly variable】
# 宣告大/小寫
declare -u u # 宣告大寫字母,聲明後可以自動把變數值轉成大寫字母
u=bQt; echo $u # 【BQT】
declare -l l # 宣告小寫字母,聲明後可以自動把變數值轉成小寫字母
l=bQt; echo $l # 【bqt】
# 輸出變數資訊
p=bqt
declare -p p # 【declare -- p="bqt"】
declare -p pp # 【bash: declare: pp: not found】
declare -p # 輸出所有變數的資訊
# 其他
declare -x x # 輸出環境變數,等同於【export x】,可以將一個變數輸出為子 Shell 的環境變數
declare -F # 輸出當前環境的所有函式名,不包含函式定義
declare -f # 輸出當前環境的所有函式,包括它的定義
declare # 等同於【set】命令,輸出當前環境的所有變數以及函式
整數的算術表示式 ((...))
算術表示式
((foo = 5 +5)) # 算術表示式,可以進行整數的算術運算,會自動忽略內部的空格
echo $? $foo # 【0 10】只要算術結果不是 0,命令就算執行成功
(( 3 - 3 ))
echo $? # 【1】如果算術結果為 0,命令就算執行失敗
echo $((2 + 2)) # 【4】算術表示式不返回值,但可在前面加上 $ 讀取算術運算的結果
echo $[2+2] # 【4】以前的語法,也可以做整數運算,不建議使用
echo $((1.5+1)) # 【syntax error】只能對整數進行運算,如果有小數會報錯
# 在 $((...)) 內部,逗號前後的兩個表示式都會執行,並返回後一個表示式的值
echo $((a=1+2, b=3*4)) # 【12】兩個表示式都會執行,並返回後一個表示式的值
echo $a $b # 【3 12】
括號中的字串
n=2; m="k"; k=n
echo $(($n + n)) # 【4】圓括號中,變數名前面的 $ 可以省略
echo $(("n" + 1)) # 【3】圓括號中的字串會認為是一個變數名
echo $(("nn" + 1)) # 【1】如果不存在同名變數,會將其作為空值,而不會報錯
echo $((k + m + n)) # 【6】動態替換
數值的進位制
Bash 的數值預設都是十進位制,但是在算術表示式中,也可以使用其他進位制。
number
:沒有任何特殊表示法的數字是十進位制數0number
:八進位制數0xnumber
:十六進位制數base#number
:base
進位制的數
echo $((0xff)) - $((2#11111111)) # 【255 - 255】
max=$(( (1<<63)-1 )); # 最大值
echo $max $((max+1)) # 【9223372036854775807 -9223372036854775808】
# 十進位制轉為其它進位制,需要使用到外部命令 bc 完成
echo "obase=2; $max" | bc # 【111...111】一共有 64 個 1
算術運算
+-*/
%
:餘數++
:自增運算--
:自減運算**
:指數運算,只有這個和 Java 等程式語言不一樣
echo $((5 / 2)) - $((5 % 2)) - $((2 ** 3)) # 【2 - 1 - 8】
echo $(( (2+3)*4 )) - $(( $((2+3)) * 4 )) # 【20 - 20】可以巢狀
i=0; j=0
echo $((i++)) - $i # 【0 - 1】作為字尾是先返回值,再進行自增運算
echo $((++j)) - $j # 【1 - 1】作為字首是先進行自增運算,再返回值
位運算
<</>>
:位的左/右
移運算,所有位向左/右
移動指定的位&|^
:位的與/或/異或
運算,對兩個數字的所有位執行一個AND/OR/異或
操作~
:位的否
運算,對一個數字的所有位取反
echo $((4>>2)) - $((4<<2)) # 【1 - 16】
echo $((17&3)) - $((2#10001 & 2#00011)) # 【1 - 1】
echo $((17|3)) - $((2#10001 | 2#00011)) # 【19 - 19】
echo $((17^3)) - $((2#10001 ^ 2#00011)) # 【18 - 18】
min=$(( (1<<63) )); # 最小值
max=$(( (1<<63)-1 )); # 最大值
echo $((~-2)) $((~-1)) $((~min)) $((~1)) $((~2)) # 【1 0 -1 -2 -3】
echo $((min-1)) $((min-2)) $((min-3)) # 【-1 -2 -3】
邏輯運算
>
<
>=
<=
==
!=
&&
||
!
:邏輯與或非expr1?expr2:expr3
:若表示式expr1
的計算結果為非零值
,則執行表示式expr2
,否則執行表示式expr3
echo $((3 > 2)) # 【1】如果邏輯表示式為真,返回 1
echo $(( (3>2) && (4<=1) )) # 【0】如果邏輯表示式為假,返回 0
echo $(( 2<1 ? 8 : 6 )) # 【6】注意,後面只能是表示式,而不是是 echo 等語句
賦值運算
parameter = value
+=
-=
*=
/=
%=
<<=
>>=
&=
|=
^=
echo $((a=1+1)) # 【2】對變數 a 進行賦值,這個式子的返回值就是等號右邊的值
echo $a # 【2】
echo $((a*=2)) # 【4】
echo $(( a>1 ? (a+=1) : (a-=1) )) # 【5】在表示式內部賦值,需要放在圓括號中
expr 和 let 命令
expr
是一款表示式計算工具,使用它也能完成以上所有 整數運算,但是運算子並不完全一樣let
命令用於將算術運算的結果,賦予一個變數。
a=3
expr 3 + 2 # 【5】運算子前後必須至少有一個空格,此表示式有返回值
expr $a + 2 # 【5】支援變數替換
expr 3.5 + 2 # 【expr: non-integer argument】也不支援非整數的運算
let x=2+3 # 表示式【x=2+3】裡面不能有空格,否則會報錯
echo $x # 【5】
2022-1-15
本文來自部落格園,作者:白乾濤,轉載請註明原文連結:https://www.cnblogs.com/baiqiantao/p/15806604.html