第二十四章 流程控制_ if分支

第二十四章 流程控制: if分支和輸入

正如許多編程語言一樣Shell也有自己的條件分支語句。有時需要根據情況進行相應的處理,因此可以通過條件分支語句實現,本章主要介紹的是if分支語句。

if語句

在Shell中if語句語法格式如下:

if commands; thencommands
[elif commmands; thencommands...]
[elsecommands]
fi

其中commands是命令列表。


例如根據變量x是否為5輸出其結果信息:

x=5if [ "$x" -eq 5 ]; thenecho "x equals 5."
elseecho "x does not equal 5."
fi

執行結果如下圖:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

本例中,將變量設置為5,通過if語句進行判斷,結果為真,因此輸出’x equals 5.‘’。

使用test

Shell不像其他編程語言直接使用條件表達式進行條件判定,在Shell中使用test進行各種檢查比較。該命令有兩種形式。第一種:


test expression



第二種,也是更流向的形式:

[ expression ]


其中,expression是一個表達式,求值結果要么為真,要么為假。如果為test返回推出狀態值0;如果為假,則返回1。

test和[其實都是命令。在bash中,兩者均為內建命令,但也作為獨立的可執行文件存在與/usr/bin中,供其它Shell使用。表達式其實就是[命令的參數,該命令同時要求將]作為其最后一個參數。

文件表達式

test文件表達式

表達式什么情況下為真
file1 -ef file2file1和file2都具有相同的i節點編號(兩個文件名通過硬鏈接指向同一個文件)
file1 -nt file2file1比file2新
file1 -ot file2file1比file2舊
-b filefile存在且為塊設備文件
-c filefile存在且為字符設備文件
-d filefile存在且為目錄
-e filefile存在
-f filefile存在且為普通文件
-g filefile存在且設置了SGID位
-G filefile存在且為有效組ID所有
-k filefile存在且設置了"粘滯位"
-L filefile存在且為符號鏈接
-O filefile存在且為有效用戶ID所有
-p filefile存在且為具名管道
-r filefile存在且可讀
-s filefile存在且不為空
-S filefile存在且為網絡套接字
-t fdfd是與終端關聯的文件描述符。該表達式可用于判斷標準輸入/輸出/錯誤是否被重定向
-u file文件存在且設置SUID位
-w filefile存在且可寫(有效用戶具有寫權限)
-x filefile存在且可執行(有效用戶具有執行/搜索權限)

例如:判讀文件~/.bashrc的文件類型及其文件狀態

代碼如下:


#!/bin/bash# test-file:評估文件的狀態FILE=~/.bashrcif [ -e FILE ]; then#判斷文件類型if [ -f FILE ]; thenecho "$FILE is a regular file."elif [ -d FILE ]; thenecho "$FILE is a directory"elif [ -b FILE ]; thenehco "$FILE is a block device file"elif [ -c FILE ]; thenecho "$FILE is a character device file"elif [ -L FILE ]; thenecho "$FILE is a symbol link file"elif [ -S FILE ]; thenecho "$FILE is a socket file"elif [ -p FILE ]; thenecho "$FILE is a pipe file"fiif [ -r FILE ]; thenecho "$FILE is readable."fiif [ -w FILE ]; thenecho "$FILE is writable."fiif [ -x FILE ]; thenecho "$FILE is executable/searchable"fielseecho "$FILE does not exist"exit 1
fi	exit

運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


字符串表達式

test的字符串表達式

表達式什么情況下為真
stringstring不為空
-n stringstring的長度大于0
-z stringstring的長度等于0
string1 == string2string1和string2相同。也可以使用單等號,但最好使用雙等號其不符號POSIX標準
string1 != string2string1和string2不相同
string1 > string2string1的排序位于string2之后
string1 < string2string1的排序位于string2之前


在使用test時,必須將表達式操作符>和<引用起來(或者通過反斜線轉義)。如果不這么做,兩者會被Shell解釋為重定向操作符,有可能會造成破壞性后果。另外還要注意,盡管Bash文檔中說過排序遵從當前語言環境的排序規則,但事實并非如此。一直到4.0版本,Bash一直使用的是ASCII(POSIX)排序。這個問題在4.1版本中才糾正過來。



例如:計算字符串的值

代碼如下:

#!/bin/bash#test-string:計算字符串值ANSWER=maybeif [ -z "$ANSWER" ]; thenecho "There is no answer." >&2exit 1
fiif [ "$ANSWER" = "yes" ]; thenecho "The answer is YES."
elif [ "$ANSWER" = "no" ]; thenecho "The answer is NO."
elif [ "$ANSWER" = "maybe" ]; thenecho "The answer is MAYBE."
elseecho "The answer is UNKNOWN."
fi

該程序運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


整數表達式

test的整數表達式

表達式什么情況下為真
integer1 eq interger2integer1等于interger2
integer1 ne interger2integer1不等于integer2
integer1 -le integer2integer1小于或等于integer2
integer1 -lt integer2integer1小于integer2
integer1 -ge integer2integer1大于或等于integer2
integer1 -gt integer2integer1大于integer2

例如:計算整數的值

代碼如下:

#!/bin/bash#test-integer: 計算整數值INT=-5if [ -z "$INT" ]; thenecho "INT is empty." >&2exit 1
fiif [ "$INT" -eq 0 ]; thenecho "INT is zero."elseif [ "$INT" -lt 0 ]; thenecho "INT is negative."elseecho "INT is positive."fiif [ $((INT % 2)) -eq 0 ]; thenecho "INT is even."elseecho "INT is odd."fi
fi

運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

更現代的test

Bash的現代版本包含了一個可以作為test增強版的復合命令,其用法如下:


[[ expression ]]



和test一樣,其中的expression是一個表達式,結果要么為真,要么為假。[[]]命令(支持所以test表達式)類似于test另外還加入一個重要的全新的字符串表達式。

string1 =~ regex



如果string1匹配ERE regex,則返回為真。例如在整數表達式的例子中,如果常量INT含有整數以為的其它值,腳本就會執行失敗。腳本需要一種方法來核實該常量包含的是整數,可以使用[[]]配合=~字符傳表達式,按照下列方式改進腳本:
#!/bin/bash#test-integer2: 計算整數值INT=-5if [[ "$INT" =~ ^-?[0-9]+$ ]]; thenif [ "$INT" -eq 0 ]; thenecho "INT is zero."elseif [ "$INT" -le 0 ]; thenecho "INT is negative."elseecho "INT is positive."fiif [ $((INT % 2)) -eq 0 ]; thenecho "INT is even."elseecho "INT is odd."fifi
elseecho "INT is not an integer." >&2exit 1
fi

運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


從運行結果來看和之前的例子運行結果相同,通過正則表達式可以判斷是否為數字。將INT的值限制為只能是以可選的減號起始,后跟一個或多個數字的字符串,同時也消除了INT為空值的可能。

[[]]的另一個特征是其中的==操作符支持和路徑擴展一樣的模式匹配。


(())-為整數設計

除了復合命令[[]],bash還支持另一種復合命令(()),它在整數操作時用得上。該命令支持所有的算術求值。

(())可用于執行算術真值測試( arithmetic truth test)。如果算術求值的結果不為0,則測試結果為真。

有了(()),可以簡化一下test-integer2的副本:

#!/bin/bash#test-integer2:計算整數的值INT=-5if [ "$INT" =~ ^-?[0-9]+$ ]; thenif ((INT == 0)); thenecho "INT is zero."elseif ((INT < 0)); thenecho "INT is negative."elseecho "INT is positive."fiif (( ((INT % 2)) == 0 )); thenecho "INT is even."elseecho "INT is odd."fielseecho "INT is not an integer." >&2exit 1
fi

(())復合命令是Shell語法的一部分,而非普通命令,并且只能處理整數,因此它能夠通過名稱來識別變量,不需要執行擴展操作。


組合表達式

將多個表達式組合在一起,形成更為復雜的測試。表達式通過邏輯操作符組合起來。test和[[]]可用的邏輯操作有3種,分別是AND、OR、NOT。test和[[]]使用不同的操作符來表示這些邏輯操作。

邏輯操作符

操作test[[]]和(())
AND-a&&
OR-o||
NOT!!

例如:判斷整數是否位于特定取值區間內

代碼如下:

#!/bin/bash#test-integer3:確定整數是否位于特定取值區間內MIN_VAL=1
MAX_VAL=100INT=50if [[ "$INT" =~ ^-?[0-9]+$ ]]; thenif [[ "$INT" -ge "$MIN_VAL"  && "$INT" -le "$MAX_VAL" ]]; thenecho "$INT is within $MIN_VAL to $MAX_VAL."elseecho "$INT is out of range."fi
elseecho "INT is not an integer." >&2exit 1
fi

運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

在該腳本中通過[[]]實現,該操作符包含由&&分隔的兩個表達式。可以使用test改寫:


if [ "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL" ]; thenecho "$INT is within $MIN_VAL to $MAX_VAL."
elseecho "$INT is out of range"
fi

否定操作符!會表達式的結果求反。例如要找出指定取值區間之外的INT值:

#!/bin/bash#test-interger4:確定整數是否位于指定取值區間之外MAX_VAL=100
MIN_VAL=1INT=50if [[ "$INT" =~ ^-?[0-9]+$ ]]; thenif [[ ! ("$INT" -ge "$MIN_VAL" && "$INT" -le "$MAX_VAL") ]]; thenecho "$INT is outside $MIN_VAL to $MAX_VAL."elseecho "$INT is in range."fielseecho "INT is not an integer." >&2exit 1
fi

運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

在表達式兩邊加上括號,用于分組。如果不見,!僅用于第一個表達式,而非兩個表達式的組合。使用test的代碼如下:

if [ ! \( "$INT" -ge "$MIN_VAL" -a "$INT" -le "$MAX_VAL"\)]; thenecho "$INT is outside $MIN_VAL to $MAX_VAL."
elseecho "$INT is in range."
fi

test和[[]]的功能基本差不多,test是長期存在的標準(也是標準Shell的POSIX規范的一部分,多用于系統啟動腳本),而[[]]是Bash(包括其它少數現代Shell)專用的。

控制操作符:另一種分支方式

Bash提供了兩種可以執行分支的操作符,即&&(AND)和||(OR)操作符,它們類似于[[]]復合命令中的邏輯操作符。&&的語法如下:


command1 && command2


|| 的語法如下:


command1 || command2


對于&&的操作符,先執行command1,僅當command1執行成功時才執行command2。對于||操作符,先執行command1,僅當command1執行失敗時才執行command2。

例如:先創建目錄,然后執行cdmingl

mkdir temp && cd temp

該命令會創建一個temp的目錄,如果創建成功,就將當前的工作目錄更改為temp。第二個命令僅在mkdir命令執行成功的情況下執行。

測試目錄temp的存在,當不存在時創建temp目錄:

[[ -d temp ]] || mkdir temp

這種結構便于在腳本中處理錯誤。

read-從標準輸入讀取值


內建的read命令可以從標準輸入讀取一行。用法如下:


read [-options] [variable…]



其中options是選項,variable是一個或多個變量,用于保存輸入值。如果未指定變量,則輸入值保存在Shell變量REPLY中。

例如:對輸入的數值進行計算

代碼如下:

#!/bin/bash#test-integer4:計算整數的值echo -n "Please enter an integer ->"
read numif [[ "$num" =~ ^-?[0-9]+$ ]]; thenif [ "$num" -eq 0 ]; thenecho "$num is zero."fiif [ "$num" -lt 0 ]; thenecho "$num is negative."elseecho "$num is positive."fiif [ (( num % 2)) -eq 0 ]; thenecho "$num is even."elseecho "$num is odd."fielseecho "$int is not an integer." >&2exit 1
fi

輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


read選項

選項描述
-a array將輸入分配給數組(從索引0開始)。
-d delimiter將字符串delimiter中的第一個字符(而非換行符)作為輸入結束
-c使用Readline處理輸入。這允許使用和命令行相同的方式編輯輸入
-i string如果用戶直接按Enter鍵,使用string作為默認值。需要配合-e選項使用
-n num從輸入中讀取num個字符,而非讀取一行
-p prompt將字符串prompt作為輸入提示來顯示
-r原始模式(raw mode)。不將反斜線解釋為轉義
-s靜默模式。在用戶輸入字符時不回顯。該模式適用于輸入密碼或其它機密信息
-t seconds超時。seconds秒之后終止輸入。如果輸入超時,read返回非0退出狀態值
-u fd從文件描述符fd(而非標準輸入)中讀取輸入

例如:讀取“機密”輸入:

代碼如下:

#!/bin/bash#read-secret:輸入"機密"if read -t 10 -sp "Enter secret passprase >" sectet_pass; thenecho -e "\nSecret passphrase = '$secret_pass' "
elseecho -e "\nInput timed out" >&2exit 1
fi

程序運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


IFS

Shell通常會對提供給read的輸入進行單詞分割。Shell變量內部字段分割符(Internal Field Separator , IFS)控制著此行為。IFS的默認值包含了空格符、制表符、換行符,它們到可用于分隔單詞。

例如:從文件讀取字段

#!/bin/bash#read-ifs: 從文件中讀取字段FILE=/etc/passwdread -p "Enter a username > "  user_namefile_info="$(grep "^$user_name:" $FILE)" #查找包含user_name的值的所在行內容if [ -n "$file_info" ]; thenIFS=":" read user pw uid gid name home shell <<< "$file_info"echo "User=     '$user'"echo "UID=      '$uid'"echo "GID=      '$gid'"echo "Full Name = '$name'"echo "Home Dir. = '$home'"echo "Shell = '$shell'"
elseecho "No such user '$user_name'" >&2exit 1
fi

運行結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

注意:read命令不能放入管道也就是說下面這種用法是禁止的:


echo “foo” | read


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85831.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85831.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85831.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

電腦網絡重置,找不到原先自家的WIFI,手機還能正常連接并上網

問題排查&#xff1a;1、電腦感覺網絡太慢&#xff0c;因此打算點擊了網絡重置 2、點擊提示會刪除網絡&#xff0c;在五分鐘后關機重啟 3、從設備管理器設備的無線wifi屬性-事件中發現刪除記錄 4、選擇更新驅動程序 5、從列表中選取 6、更改回老驅動版本 備選方案&#…

C語言_預處理詳解

1. 預定義符號 C語言設置了一些預定義符號&#xff0c;可以直接使用&#xff0c;預定義符號也是在預處理期間處理的 1 __FILE__ //進行編譯的源文件 2 __LINE__//文件當前的行號 3 __DATE__ //文件被編譯的日期 4 __TIME__//文件被編譯的時間 5 __STDC__//如果編譯器遵循ANSI…

【QT】使用QT幫助手冊找控件樣式

選擇幫助—》輸入stylesheet(小寫)—》選擇stylesheet—》右側選擇Qt Style Sheets Reference 2.使用CtrlF—》輸入要搜索的控件—》點擊Customizing QScrollBar 3.顯示參考樣式表–》即可放入QT-designer的樣式表中

SQL知識合集(二):函數篇

TRIM函數 作用&#xff1a;去掉字符串前后的空格 SELECT * FROM your_table_name WHERE TRIM(column_name) ; COALESCE函數 作用&#xff1a;返回其參數中的第一個非 NULL 值。它可以接受多個參數&#xff0c;并從左到右依次評估這些參數&#xff0c;直到找到第一個非 NUL…

Cursor 工具項目構建指南: Uniapp Miniprogram 環境下的 Prompt Rules 約束

簡簡單單 Online zuozuo: 簡簡單單 Online zuozuo 簡簡單單 Online zuozuo 簡簡單單 Online zuozuo 簡簡單單 Online zuozuo :本心、輸入輸出、結果 簡簡單單 Online zuozuo : 文章目錄 Cursor 工具項目構建指南: Uniapp Miniprogram 環境下的 Prompt Rules 約束前言項目簡…

Java轉Go日記(六十):gin其他常用知識

1. 日志文件 package mainimport ("io""os""github.com/gin-gonic/gin" )func main() {gin.DisableConsoleColor()// Logging to a file.f, _ : os.Create("gin.log")gin.DefaultWriter io.MultiWriter(f)// 如果需要同時將日志寫入…

cocos單例工廠和自動裝配

cocos單例工廠和自動裝配 1 單例工廠 1.1 分析 實例字典 原理很簡單&#xff0c;只是一個map&#xff0c;確保每個類只保留一個實例&#xff1b; private static _instances new Map<string, any>();獲取與存儲實例 這邊使用的方式是生成一個唯一的id存儲在類上&…

django paramiko 跳轉登錄

在使用Django框架結合Paramiko進行SSH遠程操作時&#xff0c;通常涉及到自動化腳本的執行&#xff0c;比如遠程服務器上的命令執行、文件傳輸等。如果你的需求是“跳轉登錄”&#xff0c;即在登錄遠程服務器后&#xff0c;再通過該服務器的SSH連接跳轉到另一臺服務器&#xff0…

《C++初階之類和對象》【命名空間 + 輸入輸出 + 缺省參數 + 函數重載】

【命名空間 輸入&輸出 缺省參數 函數重載】目錄 前言&#xff1a;---------------hello world---------------比較C語言和C的第一個程序&#xff1a;hello word ---------------命名空間---------------什么是命名空間&#xff1f;怎么使用命名空間&#xff1f;怎么定義…

[USACO1.5] 八皇后 Checker Challenge Java

import java.util.*;public class Main {// 標記 對角線1&#xff0c;對角線2&#xff0c;所在x軸 是否存在棋子static boolean[] d1 new boolean[100], d2 new boolean[100], d new boolean[100]; static int n, ans 0;static int[] arr new int[14]; // 記錄一輪棋子位置…

云服務器Xshell登錄拒絕訪問排查

根據你的描述&#xff0c;使用Xshell 8登錄云服務器時顯示“拒絕訪問”&#xff0c;可能涉及多個原因。以下結合搜索結果整理出排查和解決方法&#xff0c;按優先級排序&#xff1a; 一、檢查基礎網絡與端口連通性 本地網絡與服務器IP是否可達 在本地電腦的CMD中執行 ping 服務…

Python爬蟲實戰:研究urlunparse函數相關技術

1. 引言 1.1 研究背景與意義 在當今信息爆炸的時代,互聯網上的數據量呈現出指數級增長。如何從海量的網頁數據中高效地獲取有價值的信息,成為了學術界和工業界共同關注的問題。網絡爬蟲作為一種自動獲取網頁內容的技術,能夠按照預定的規則遍歷互聯網上的網頁,并提取出所需…

Spring AI學習一

隨著Chatpt的火爆&#xff0c;現在Spring官方也開始支持AI了并推出了Spring AI框架&#xff0c;目前還沒發布正式版本&#xff0c;這里可以先看一下官方依賴的版本。 Spring官網地址可以看這里&#xff1a;Spring | Home 目前官網上是有這兩個版本&#xff1a;1.0.0和1.1.0-SN…

reverse筆記

一&#xff0c;strcat的使用方法&#xff08;在攻防世界中刷題時遇到的&#xff09; 二&#xff0c;殼&#xff08;做題遇到過但是一直不是很理解&#xff0c;今天查了一下&#xff09; 殼是一種軟件保護技術&#xff0c;能夠防止程序被輕易地分析和修改。 總而言之&#xff0…

spring4第7-8課-AOP的5種通知類型+切點定義詳解+執行順序

繼續學習&#xff0c;方便自己復查記錄 ①AOP簡介&#xff1a; 面向切面編程(也叫面向方面編程)&#xff1a;Aspect Oriented Programming(AOP)。 Spring框架中的一個重要內容。。 通過預編譯方式和運行期間動態代理實現在不修改源代碼的情況下給程序動態統一添加功能…

EscapeX:去中心化游戲,開啟極限娛樂新體驗

VEX 平臺推出全新去中心化游戲 EscapeX&#xff08;數字逃脫&#xff09;&#xff0c;創新性地將大逃殺玩法與區塊鏈技術相融合。用戶不僅能暢享緊張刺激的解謎過程&#xff0c;更能在去中心化、公正透明的環境中參與游戲。EscapeX 的上線&#xff0c;為 VEX 生態注入全新活力&…

Multi Agents Collaboration OS:Web DeepSearch System

背景&#xff1a;多智能體協作驅動網絡信息處理的范式革新 隨著大型語言模型&#xff08;LLM&#xff09;能力的突破性進展&#xff0c;人工智能正從“單點賦能”向“系統協同”演進。傳統單一智能體在復雜業務場景中逐漸顯露局限&#xff1a;面對需多維度知識整合、動態任務拆…

React 第五十三節 Router中 useRouteError 的使用詳解和案例分析

前言 useRouteError 是 React Router v6.4 引入的關鍵錯誤處理鉤子&#xff0c;用于在 路由錯誤邊界&#xff08;Error Boundary&#xff09; 中獲取路由操作過程中發生的錯誤信息。 它提供了優雅的錯誤處理機制&#xff0c;讓開發者能夠創建用戶友好的錯誤界面。 一、useRou…

[arthas]arthas安裝使用

arthas是阿里開源的一個java線上監控以及診斷工具&#xff0c;在docker容器中我們無需重啟服務&#xff0c;也不用更改代碼&#xff0c;就可以完成對應用內存、線程、日志級別的修改、方法調用的出入參、異常監測、執行耗時等&#xff0c;xxxx.xxxx.xxxxx為脫敏內容 1. 在docke…

Flask-Babel 使用示例

下面創建一個簡單的 Flask-Babel 示例&#xff0c;展示如何在 Flask 應用中實現國際化和本地化功能。這個示例將包括多語言支持&#xff08;中文和英文&#xff09;、語言切換功能以及翻譯文本的使用。 項目結構 我們將創建以下文件結構&#xff1a; 1. 首先&#xff0c;創…