Shell編程-03-Shell中的特殊變數和擴展變數

来源:https://www.cnblogs.com/surpassme/archive/2018/11/09/9932841.html
-Advertisement-
Play Games

特殊變數     在Shell中的特殊變數主要分別兩種 位置參數變數 、 狀態變數 兩種。 位置參數變數     Shell中的位置參數變數主要是指\$0、\$1、\$ 等,主要用於從命令行、函數或腳本執行等地方傳遞參數。詳細說明如下所示: \$0 :獲取當前 ...


特殊變數

    在Shell中的特殊變數主要分別兩種位置參數變數狀態變數兩種。

位置參數變數

    Shell中的位置參數變數主要是指$0、$1、$#等,主要用於從命令行、函數或腳本執行等地方傳遞參數。詳細說明如下所示:

  • $0:獲取當前執行的Shell腳本的文件名,如腳本中包含路徑,則輸出也包括路徑
  • $n:獲取當前執行的Shell腳本的第n個參數值,如n>9,則需要使用用大括弧,如${10},各參數間用空格進行分隔
  • $#:獲取當前執行的Shell腳本傳入參數的總個數
  • $*:獲取當前執行的Shell所有傳入參數,如不加引號則與$@功能相同,如果添加雙引號**"$*",則表示將所有傳入參數視為單個字元串**,相當於"$1 $2 $3"
  • $@:獲取當前執行的Shell所有傳入參數,**如不加引號則與$*功能相同,如果添加雙引號"$@",則表示將所有傳入參數視為獨立的字元串**,相當於"$1" "$2" "$3"

當"$*"和"$@"都添加雙引號時,兩者的功能有所區別;如不加,則功能相同,無區別。

位置參數變數示例

1、示例一:

[root@localhost Test]# cat para.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
echo '$0  is:' $0
echo '$1  is:' $1
echo '$12 is:' ${12}
echo '$#  is:' $#
echo '$*  is:' $*
echo '"$*"is:' "$*"
echo '$@  is:' $@
echo '"$@"is:' "$@"
# 輸出結果
[root@localhost Test]# bash ~/Test/para.sh {a..z}
a b c d e f g h i j k l m n o
$0  is: /root/Test/para.sh
$1  is: a
$12 is: l
$#  is: 26
$*  is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"$*"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
$@  is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"$@"is: a b c d e f g h i j k l m n o p q r s t u v w x y z

1、傳入的參數個數多於腳本定義的參數時,則多出的參數會忽略
2、傳入的參數中如使用雙引號,則會當作一個參數值進行傳遞
3、位置參數如大於9,需要使用${}進行傳遞

2、示例二:

[root@localhost Test]# cat testposition.sh 
#!/bin/bash
echo '$# $1 $2 $3 $* $@'
echo $# $1 $2 $3 $*  $@
echo "************"
echo '$*'
for tmp in $*
 do
   echo $tmp
 done
echo "************"
echo "@@@@@@@@@@@@"
echo '$@'
for temp in $@
 do
  echo $temp
 done
echo "@@@@@@@@@@@@"

echo '"*"*"*"*"*"*'

echo '$*'
for i in "$*"
 do
   echo $i
 done
echo '"*"*"*"*"*"*'

echo '"@"@"@"@"@"@'

echo '$@'
for j in "$@"
 do
  echo $j
 done
echo '"@"@"@"@"@"@'

[root@localhost Test]# bash testposition.sh  "Hello Jack" Welcome "to Shanghai"
$# $1 $2 $3 $* $@
3 Hello Jack Welcome to Shanghai Hello Jack Welcome to Shanghai Hello Jack Welcome to Shanghai
************
$* # 未加雙引號,所以會輸出全部參數,則第一個和第三個參數會拆開
Hello
Jack
Welcome
to
Shanghai
************
@@@@@@@@@@@@
$@ # 未加雙引號,所以會輸出全部參數,則第一個和第三個參數會拆開
Hello
Jack
Welcome
to
Shanghai
@@@@@@@@@@@@
"*"*"*"*"*"*
$* # 添加雙引號後,傳入的參數全部當一個參數進行輸出
Hello Jack Welcome to Shanghai
"*"*"*"*"*"*
"@"@"@"@"@"@
$@ # 添加雙引號後,傳入的參數全部當獨立的參數進行輸出
Hello Jack
Welcome
to Shanghai
"@"@"@"@"@"@

狀態變數

  • $?:獲取上一個命令或腳本的執行狀態值(0:成功,其他:失敗)
  • $$:獲取當前執行的Shell的進程號(PID)
  • $!:獲取上一個在後臺工作的進程的進程號
  • **$_**:獲取在些之前執行的命令或腳本的最後一個參數

以上四個狀態變數,僅$?常用,其他三個瞭解即可。

在日常使場景中,$?主要用法如下所示:

  • 1、判斷命令和腳本是否執行成功
  • 2、如腳本中調用exit 數字,則會返回該數字給$?
  • 3、如在函數中,則可以通過return 數字將該數字返回給$?

狀態變數示例

1、$?示例:

[root@localhost Test]# ll /etc/profile
-rw-r--r--. 1 root root 1819 4月  11 2018 /etc/profile
[root@localhost Test]# echo $?
0
[root@localhost Test]# ll /etc/profild
ls: 無法訪問/etc/profild: 沒有那個文件或目錄
[root@localhost Test]# echo $?
2

2、$$示例:

[root@localhost Test]# cat testPID.sh
#!/bin/bash
echo $$ > /tmp/test.pid
sleep 300

[root@localhost Test]# bash testPID.sh  & # 將當前腳本調用到後臺執行
[1] 1671
[root@localhost Test]# ps -ef | grep testPID | grep -v grep
root      1671 23706  0 16:37 pts/0    00:00:00 bash testPID.sh # 查詢PID

3、$!示例:
    $!功能類似於$$,只不過是獲取上一次執行腳本的PID

[root@localhost Test]# bash testPID.sh  &
[1] 24078
[root@localhost Test]# echo $!
24078 # 列印上一次在後臺執行的進程號
[root@localhost Test]# ps -ef | grep testPID | grep -v grep
root     24078 23706  0 16:42 pts/0    00:00:00 bash testPID.sh

4、$_示例:

[root@localhost Test]# bash para.sh {a..z}
a b c d e f g h i j k l m n o
$0  is: para.sh
$1  is: a
$12 is: l
$#  is: 26
$*  is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"$*"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
$@  is: a b c d e f g h i j k l m n o p q r s t u v w x y z
"$@"is: a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@localhost Test]# echo $_
z # 列印最後一個傳入的參數值

Bash 內置變數

    常用的內部命令有echo、eval、exec、export、read、shift、exit

echo

    主要用於列印信息,其命令格式如下所示:

echo [options] args

常用參數如下所示:

參數選項 說明
-n 不換行輸出內容
-e 解析轉義字元

echo常用轉義字元如下:

轉義字元 說明
\n 換行
\r 回車
\t Tab
\b 退格
\v 縱向製表符
eval

    當Shell程式運行到eval語句時,將讀入參數args,並將它們組合成一個新的命令而後執行。其命令格式如下所示:

eval args
exec

    exec主要用於在不創建新的子進程的情況下,轉而執行指定的命令,當指定命令執行完後,則終止該進程。其命令格式如下所示:

exec args

當使用exec打開文件後,read命令每次都會將文件指針移動到下一行進行讀取,直至結束。因此常用來處理文件內容。

read

    從標準輸入讀取變數或字元串等信息並傳遞給其他變數,其命令格式如下所示

read args
shift

    對傳入的位置參數依次向左移動一個位置,並使用位置參數$#減1,直至0為止。其命令格式如下所示:

shift postition args

shift如果不帶參數,則預設左移1位
如傳入的參數為$1 $2 $3,如執行一次shift,則之前的$3變成$2,$2變成$1,$1消失。

exit

    常用於退出Shell,在日常使用過程中可使用exit num來自定義返回狀態數。

Bash 內置變數示例

1、echo

[root@localhost Test]# echo "Test";echo "Dao"
Test
Dao
[root@localhost Test]# echo -n "Test";echo "Dao"
TestDao
[root@localhost Test]# echo -e "Test\tName\n Dao"
Test    Name
 Dao

2、eval

[root@localhost Test]# cat eval.sh
#!/bin/bash

echo "No eval"
echo \$$#
echo "Add eval"
eval echo \$$#

[root@localhost Test]# bash eval.sh  a b
No eval
$2 # 未添加evel時,$#為2,則輸出$2
Add eval
b  # 添加evel後,則重新對傳入的參數進行解析,則輸出傳入的第2個參數

3、exec

[root@localhost Test]# exec ls
eval.sh  para.sh  ping.sh  testPID.sh  testposition.sh
[admin@localhost ~]$  # 在執行exec後則終止當前Shell進程,因此從root用戶退出到普通用戶
# 與read一起讀取文件
[root@localhost ~]# seq 5 > /tmp/rand.log
[root@localhost ~]# cat /tmp/rand.log 
1
2
3
4
5
[root@localhost Test]# cat exec.sh
#!/bin/bash
exec < /tmp/rand.log
while read line
 do
  echo $line
 done
echo "Completed"

[root@localhost Test]# bash exec.sh
1
2
3
4
5
Completed

4、read
可以參考公眾號中read命令一文

5、shift

[root@localhost Test]# cat shift.sh
#!/bin/bash
echo $1 $2 $3 $4 $5
until [ -z $1 ]
do
  echo $@
  shift 1
done
[root@localhost Test]# bash shift.sh {1..5}
1 2 3 4 5
1 2 3 4 5
2 3 4 5
3 4 5
4 5
5

變數擴展

變數擴展說明

    Shell中變數擴展說明如下所示:

  • ${var}:返回${var}的內容
  • ${#var}:返回${var}的字元長度
  • ${var:offset}:返回${var}從位置offset之後開始提取字元至結束
  • ${var:offset:length}:返回${var}從offset之後,提取長度為length的字元
  • ${var#word}:返回從${var}開頭開始刪除最短匹配的word子符串
  • ${var##word}:返回從${var}開頭開始刪除最長匹配的word子符串
  • ${var%word}:返回從${var}結尾開始刪除最短匹配的word子符串
  • ${var%%word}:返回從${var}結尾開始刪除最長匹配的word子符串
  • ${var/oldstring/newstring}:使用newstring替換第一個匹配的字元oldstring
  • ${var//oldstring/newstring}:使用newstring替換所有匹配的字元oldstring
  • ${var:-word}:如果變數var的值為空或未賦值,則將word做為返回值,常用於防止變數為空或未定義而導致的異常
  • ${var:=word}:如果變數var的值為空或未賦值,則將word賦值給var並返回其值。
  • ${var:?word}:如果變數var的值為空或未賦值,則將word做為標準錯誤輸出,否則則輸出變數的值,常用於捕捉因變數未定義而導致的錯誤並退出程式
  • ${var:+word}:如果變數var的值為空或未賦值,則什麼都不做,否則word字元將替換變數的值
其中${var:-word}、${var:=word}、${var:?word}、${var:+word}中的冒號也可以省略,則將變數為空或未賦值修改為未賦值,去掉了為空的檢測, 即運算符僅檢測變數是否未賦值

變數擴展示例

[root@localhost init.d]# var="This is test string"
[root@localhost init.d]# echo $var
This is test string
[root@localhost init.d]# echo ${var}
This is test string
[root@localhost init.d]# echo ${#var} # 統計字元長度
19
[root@localhost init.d]# echo ${var:5} # 從第5個位置開始截取字元
is test string
[root@localhost init.d]# echo ${var:5:2} # 從第5個位置開始截取2個字元
is
[root@localhost init.d]# echo ${var#This} # 從開頭刪除最短匹配的字元 is
is test string
[root@localhost init.d]# echo ${var##This}  # 從開頭刪除最長匹配的字元 is
is test string
[root@localhost init.d]# echo ${var%g} # 從結尾刪除最短匹配的字元 is
This is test strin
[root@localhost init.d]# echo ${var%%g} # 從結尾刪除最長匹配的字元 is
This is test strin
[root@localhost init.d]# echo ${var/is/newis} # 替換第一個匹配的字元
Thnewis is test string
[root@localhost init.d]# echo ${var//is/newis} # 替換所有匹配到的字元
Thnewis newis test string

[root@localhost init.d]# echo $centos # 變數未定義

[root@localhost init.d]# echo ${centos:-UNDEFINE} # 變數為空,返回UNDEFINE
UNDEFINE
[root@localhost init.d]# centos="CentOS"
[root@localhost init.d]# echo ${centos:-UNDEFINE} # 變數已經定義,返回變數本身的值
CentOS
[root@localhost init.d]# unset centos # 取消變數值
[root@localhost init.d]# echo $centos

[root@localhost init.d]# result=${centos:=UNDEFINE}
[root@localhost init.d]# echo $result
UNDEFINE
[root@localhost init.d]# echo $centos # 變數值為空,則將UNDEFINE賦值給centos
UNDEFINE
[root@localhost init.d]# unset centos
[root@localhost init.d]# echo ${centos:?can not find variable centos}

-bash: centos: can not find variable centos  # 變數值為空,輸出自定義錯誤信息

[root@localhost init.d]# centos="IS DEFINED"
[root@localhost init.d]# echo ${centos:?can not find variable centos}
IS DEFINED               #變數值已定義,則輸出變數值
[root@localhost init.d]# unset centos
[root@localhost init.d]# echo ${centos:+do nothing} # 變數值為空,什麼都不操作輸出

[root@localhost init.d]# centos="do"
[root@localhost init.d]# echo ${centos:+do nothing}  # 變數已賦值,則輸出自定義的消息
do nothing

本文同步在微信訂閱號上發佈,如各位小伙伴們喜歡我的文章,也可以關註我的微信訂閱號:woaitest,或掃描下麵的二維碼添加關註:
MyQRCode.jpg


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本類思想:高性能計數器以微妙級累加數值,逢十進位。如果動態的單看數值最後一個數字,一定是在0-9之間不斷旋轉,就像一個滾動的俄羅斯輪盤,暫停時一定指向其中某一位數字並且指向哪個數字是不可預測的,當暫停次數足夠多時,分佈在各個數值上的概率無限接近。 寫作時間:2018-11-07 本文只代表本人的見解 ...
  • 用Aspose組件的優點是操作Word文檔不需要安裝Office就可以實現。 首先需要引用Aspose.Words.dll,鏈接地址:鏈接:https://pan.baidu.com/s/1rJvjp-kMsEterYf_oud28Q 提取碼:awiw 代碼如下: ...
  • 在很早之前的隨筆裡面,已經介紹了WInform框架中工作流模塊的功能,不過由於工作流模塊中界面處理部分比較麻煩,一直沒有在Bootstrap框架中進行集成,最近由於項目的關係,花了不少精力,把工作流模塊重新梳理遷移到Bootstrap框架上,本篇隨筆主要介紹基於Metronic的Bootstrap開... ...
  • 一、CLR 線程池基礎 一般來說如果電腦的 CPU 利用率沒有 100% ,那麼說明很多進程的部分線程沒有運行。可能在等待 文件/網路/資料庫等設備讀取或者寫入數據,又可能是等待按鍵、滑鼠移動等事件。 執行 I/O 限制的操作時,操作系統通過設備驅動程式通知硬體幹活,而 CPU 處於一種空閑狀態。 ...
  • head 與 tail 就像它的名字一樣的淺顯易懂,它是用來顯示開頭或結尾某個數量的文字區塊,head 用來顯示檔案的開頭至標準輸出中,而 tail 想當然爾就是看檔案的結尾。 一.命令格式: head [參數]... [文件]... 二.命令功能: head 用來顯示檔案的開頭至標準輸出中,預設h ...
  • e2image e2Image程式將位於設備上的ext2、ext3或ext4文件系統元數據保存到由圖像文件指定的文件中。通過對這些程式使用-i選項,image文件可以由dupe2fs和調試器來檢查。這可以幫助專家恢復嚴重損壞的文件系統。 如果image文件是”-“,那麼e2image的輸出將被髮送到 ...
  • rar解壓 ...
  • Linux 提供了許多用於文件搜索的命令,這些命令都很強大,但是也有一些不同之處,這裡分別介紹一下。 一、find 命令 find 是最常見和最強大的一個文件搜索命令。使用 find 命令可以在指定目錄中搜索指定的文件。語法如下: 其中,目錄是 find 命令將要去搜索的目錄,包括該目錄及其子目錄, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...