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

来源:https://www.cnblogs.com/alongdidi/archive/2019/12/09/bash_variable_and_multi-cmd-run.html
-Advertisement-
Play Games

變數基礎知識 程式由指令加數據所組成,而變數可以理解為數據來源的一種。 變數名可以理解為指向了某個記憶體空間的地址,對於變數的賦值可理解為向記憶體空間寫入數據,對於變數的引用可理解為從記憶體空間讀取數據。 變數有類型的概念(例如字元串、數字等),不同的類型決定了數據的存儲格式、可表示的數據範圍以及可參與的 ...


變數基礎知識

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

變數名可以理解為指向了某個記憶體空間的地址,對於變數的賦值可理解為向記憶體空間寫入數據,對於變數的引用可理解為從記憶體空間讀取數據。

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

在編程語言中,可以根據變數的強弱來劃分。例如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對某些字元的特殊作用(例如美元符號$,就會做一些變數展開或者特殊符號的處理)。而引號則是引用的其中兩種方式(單引號和雙引號)。

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

[root@c7-server ~]# name=zwl
[root@c7-server ~]# echo '${name}'
${name}
[root@c7-server ~]# echo "${name}"
zwl

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

[root@c7-server ~]# echo ${name}
alongdidi
[root@c7-server ~]# echo ${name:2:3}
ong
[root@c7-server ~]# echo $name:2:3
alongdidi:2:3

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

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

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

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

[root@c7-server ~]# unset name
[root@c7-server ~]# echo $name

[root@c7-server ~]# set | grep "^name"
[root@c7-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)。

[root@c7-server ~]# readonly age=28
[root@c7-server ~]# age=30
-bash: age: readonly variable
[root@c7-server ~]# unset age
-bash: unset: age: cannot unset: readonly variable

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

[root@c7-server ~]# 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中應該是不存在的,我們來證明一下。

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

[root@c7-server ~]#

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

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

[root@c7-server ~]# exit
exit
[root@c7-server ~]# echo $name
alongdidi

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

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

[root@c7-server ~]#

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

環境變數

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

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

[root@c7-server ~]# export name
[root@c7-server ~]# bash
[root@c7-server ~]# echo $name
alongdidi
[root@c7-server ~]# bash
[root@c7-server ~]# echo $name
alongdidi
[root@c7-server ~]# bash 
[root@c7-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

 

 


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

-Advertisement-
Play Games
更多相關文章
  • abp依賴註入的原理剖析 請先移步參考 "[Abp vNext 源碼分析] 3. 依賴註入與攔截器" 本文此篇文章的補充和完善。 abp的依賴註入最後是通過IConventionalRegister介面的AddType方法實現的。先看下該介面: 該介面定義了三個方法,支持傳入程式集、類型數組、具體類 ...
  • 使用abp模板進行項目開發: 1:準備工作:我使用v2.x版本,所以會依賴.net core 2.2 查看並更新本地環境: 更新.net core版本:cmd 運行 dotnet --version查看本機版本(我的是core 2.1) 通過下載安裝sdk更新core版本:https://dotne ...
  • 下麵是針對 nfs 所有的版本,我們可以通過不同的RFC 進行詳細看其RFC的細節來進行對比: 下麵是備忘一些NFS RFC 的鏈接: https://datatracker.ietf.org/doc/search?name=nfs&sort=&rfcs=on&activedrafts=on nfs ...
  • 關鍵詞:top、perf、sar、ksar、mpstat、uptime、vmstat、pidstat、time、cpustat、munin、htop、glances、atop、nmon、pcp-gui、collectl。 1. top top是最常用的查看系統資源使用情況的工具,包括CPU、記憶體等等 ...
  • * * * * * (下麵的字體對應) 分 時 日 月 周 星號(*):代表所有可能的值,例如month欄位如果是星號,則表示在滿足其它欄位的制約條件後每月都執行該命令操作。 逗號(,):可以用逗號隔開的值指定一個列表範圍,例如,“1,2,5,7,8,9” 中杠(-):可以用整數之間的中杠表示一個整 ...
  • 準備環境 軟體安裝 服務端基本配置文件 創建一個新的 PKI 和 CA 生成服務端證書 簽約服務端證書 創建 Diffie Hellman 客戶端基本配置 生成客戶端證書 最後簽約客戶端證書 證書整理 服務端 客戶端 server.conf 密碼驗證腳本 !/bin/sh PASSFILE="/et ...
  • 準備環境 環境測試 軟體安裝 xl2tpd.conf options.xl2tpd ipsec.conf l2tp ipsec.conf chap secrets 也就是我們一會在windows上登陸時用到的帳號和密碼 default secrets sysctl.conf 檢查配置 防火牆 開啟服 ...
  • 準備環境 軟體安裝 pptpd.conf options.pptpd chap secrets 也就是我們一會在windows上登陸時用到的帳號和密碼 sysctl.conf 啟動服務並查看埠 防火牆 主機連接 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...