網站首頁 編程語言 正文
1.概述
到目前為止,編寫的腳本都缺少一個常用于大多數計算機程序的特性–交互性,或者說與用戶互動的能力。盡管很多程序并不需要是交互式的,但能夠直接接受用戶輸入,確實有利于某些程序。
2. read從標準輸入讀取值
內建命令read可用于從標準輸入中讀取一行。該命令可以讀取鍵盤輸入,如果使用了重定向,也可以讀取文件的數據行。該命令用法如下:
read [-options] [variable...]
其中,option是一個或多個選項,variable是一個或多個變量,用于保存輸入值。如果未指定變量,則輸入值保存在Shell變量REPLAY中。使用read命令改寫之前的整數驗證腳本:
#!/bin/bash # read-integer echo -n "Please enter an integer -> " read int if [[ "$int" =~ ^-?[0-9]+$ ]]; then ? ? ? ? if [ "$int" -eq 0 ]; then ? ? ? ? ? ? ? ? echo "$int is zero." ? ? ? ? else ? ? ? ? ? ? ? ? if [ "$int" -lt 0 ]; then ? ? ? ? ? ? ? ? ? ? ? ? echo "$int is negative." ? ? ? ? ? ? ? ? else ? ? ? ? ? ? ? ? ? ? ? ? echo "$int is positive" ? ? ? ? ? ? ? ? fi ? ? ? ? fi ? ? ? ? if [ $((int % 2)) -eq 0 ]; then ? ? ? ? ? ? ? ? echo "$int is even." ? ? ? ? else ? ? ? ? ? ? ? ? echo "$int is odd." ? ? ? ? fi else ? ? ? ? echo "Input value is not an integer." >&2 ? ? ? ? exit 1 fi
read也可以將輸入賦給多個變量
[sysadmin@ansible bin]$ cat read1 #!/bin/bash #read-multiple echo -n "Enter one or more values > " read var1 var2 var3 var4 var5 echo "var1 = '$var1'" echo "var2 = '$var2'" echo "var3 = '$var3'" echo "var4 = '$var4'" echo "var5 = '$var5'" [sysadmin@ansible bin]$ read1 Enter one or more values > 1 2 3 4 5 var1 = '1' var2 = '2' var3 = '3' var4 = '4' var5 = '5'
如果read接收到的值數量少于預期,則多出的變量為空值,如果數量多于預期,則額外的輸入全部保存在最后一個變量中。
[sysadmin@ansible bin]$ cat read1 #!/bin/bash #read-multiple echo -n "Enter one or more values > " read var1 var2 var3 var4 var5 echo "var1 = '$var1'" echo "var2 = '$var2'" echo "var3 = '$var3'" echo "var4 = '$var4'" echo "var5 = '$var5'" [sysadmin@ansible bin]$ read1 Enter one or more values > a var1 = 'a' var2 = '' var3 = '' var4 = '' var5 = '' [sysadmin@ansible bin]$ read1 Enter one or more values > a b c d e f g var1 = 'a' var2 = 'b' var3 = 'c' var4 = 'd' var5 = 'e f g' [sysadmin@ansible bin]$
如果沒有為read命令指定變量,則所有的輸入全部保存在Shell變量REPLY中
[sysadmin@ansible bin]$ cat read2 #!/bin/bash #read-multiple echo -n "Enter one or more values > " read echo "REPLY = '$REPLY'" [sysadmin@ansible bin]$ read2 Enter one or more values > a b c d REPLY = 'a b c d' [sysadmin@ansible bin]$
2.1 read選項
選項 | 描述 |
---|---|
-a array | 將輸入分配給數組(從索引0開始)。 |
-d delimiter | 將字符串delimter中的第一個字符(而非換行符)作為輸入的結束 |
-e | 使用readline處理輸入,允許使用和命令行相同的方式編輯輸入 |
-i string | 如果用戶直接按Enter鍵,使用string作為默認值,需要配合-e選項使用 |
-n num | 從輸入中讀取num個字符,而非讀取一整行 |
-p prompt | 將字符prompt作為輸入提示來顯示 |
-r | 原始模式,不將反斜線符解釋為轉義 |
-s | 靜默模式,在用戶輸入字符時不回顯,該模式適用于輸入密碼或其他機密信息 |
-t seconds | 超時,seconds秒之后終止輸入,如果輸入超時,read返回非0退出狀態值 |
-u fd | 從文件描述符fd中讀取輸入 |
選項-p
[sysadmin@ansible bin]$ cat read2
#!/bin/bash
#read-single
read -p "Enter one or more values > "
echo "REPLY = '$REPLY'"
[sysadmin@ansible bin]$ read2
Enter one or more values > a
REPLY = 'a'
[sysadmin@ansible bin]$
選項-t和-s
[sysadmin@ansible bin]$ cat readpass
#!/bin/bash
#read-pass
if read -t 10 -sp "Enter password > " passwd; then
? ? ? ? echo -e "\nSecret passphrase = '$passwd'"
else
? ? ? ? echo -e "\nInput timed out" >&2
? ? ? ? exit 1
fi
[sysadmin@ansible bin]$ readpass
Enter password >
Secret passphrase = 'abcdef'
[sysadmin@ansible bin]$
選項-e和-i
[sysadmin@ansible bin]$ cat readdefault
#!/bin/bash
#read-default
read -e -p "What is your user name? " -i $USER
echo "You answered: '$REPLY'"
[sysadmin@ansible bin]$ readdefault
What is your user name? sysadmin
You answered: 'sysadmin'
[sysadmin@ansible bin]$
2.2 IFS
Shell通常會提供給read的輸入進行單詞分割,這意味著輸入行中被一個或多個空白字符分割的多個單詞會變成若干獨立項,再由read分配給各個變量。Shell變量內部字段分割符(Internal Filed Separator,IFS)控制著此行為。IFS的默認值包含了空格符,制表符,換行符,它們都可用于分割單詞。
我們可以調整IFS的值,控制read的輸入字段。例如:/etc/passwd文件中的數據行采用冒號作為字段分隔符。將IFS的值改成冒號,就可以使用read讀入/etc/passwd的內容并順利將字段分割存入各個變量。來看下面的實現腳本。
[sysadmin@ansible bin]$ cat read-ifs
#!/bin/bash
# read-ifs
FILE=/etc/passwd
read -p "Enter a user > " user_name
file_info="$(grep "^$user_name:" $FILE)"
if [ -n "$file_info" ]; then
? ? ? ? IFS=":" 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'"
else
? ? ? ? echo "No such user '$user_name'" >&2
? ? ? ? exit 1
fi
[sysadmin@ansible bin]$ read-ifs
Enter a user > jticnoc
User = ? ? ? ? ?'jticnoc'
UID = ? ? ? ? ? '2099'
GID = ? ? ? ? ? '2099'
Full Name = ? ? ''
Home Dir = ? ? ?'/home/jticnoc'
Shell = ? ? ? ? '/bin/bash'
[sysadmin@ansible bin]$
Shell允許一個或多個變量賦值直接出現在命令之前。這些賦值會修改緊隨其后的命令的環境。這種賦值效果是臨時的。對環境所作的改動僅限于命令執行期間有效。<<< 標識here string。here string類似于here document,但是更簡短,僅由單個字符串組成。
2.3 驗證輸入
好程序和差程序之間的區別往往在于處理意外情況的能力,而意外情況多以錯誤輸入的形式出現。重要的是,每次程序接收到輸入的時候,都要執行此類檢查,以防止非法數據。
[sysadmin@ansible bin]$ cat read-validate
#!/bin/bash
#read-validate
invalid_input () {
? ? ? ? echo "Invalid input '$REPLAY'" >&2
? ? ? ? exit 1
}
read -p "Enter a single item > "
# input is null
[[ -z "$REPLY" ]] && invalid_input
# input is multi items
(( "$(echo "$REPLY" |wc -w)" > 1 )) && invalid_input
# input filename is valid
if [[ "$REPLY" =~ ^[-[:alnum:]\._]+$ ]]; then
? ? ? ? echo "'$REPLY' is a valid filename."
? ? ? ? if [[ -e "$REPLY" ]]; then
? ? ? ? ? ? ? ? echo "And file '$REPLY' exists."
? ? ? ? else
? ? ? ? ? ? ? ? echo "However, file '$REPLY' does not exist."
? ? ? ? fi
? ? ? ? # input is float
? ? ? ? if [[ "$REPLY" =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then
? ? ? ? ? ? ? ? echo "'$REPLY' is a floating point number."
? ? ? ? else
? ? ? ? ? ? ? ? echo "'$REPLY' is not a floating point number."
? ? ? ? fi
? ? ? ? # input is int
? ? ? ? if [[ "$REPLY" =~ ^-?[[:digit:]]+$ ]]; then
? ? ? ? ? ? ? ? echo "'$REPLY' is an integer."
? ? ? ? else
? ? ? ? ? ? ? ? echo "'$REPLY' is not an integer."
? ? ? ? fi
else
? ? ? ? echo "The string '$REPLY' is not a valid filename."
fi
[sysadmin@ansible bin]$
2.4 菜單
菜單驅動是一中常見的交互方式,菜單驅動的程序會為用戶呈現一系列的選項,要求用戶從中選擇。
[sysadmin@ansible bin]$ cat read-menu
#!/bin/bash
#read-menu
clear
echo "
Please Select:
1.Display System Information
2.Display Disk Space
3.Display Home Space Utilization
4.Quit
"
read -p "Enter selection [0-3] > "
if [[ "$REPLY" =~ ^[0-3]$ ]]; then
? ? ? ? if [[ "$REPLY" == 0 ]]; then
? ? ? ? ? ? ? ? echo "Program terminated."
? ? ? ? ? ? ? ? exit
? ? ? ? fi
? ? ? ? if [[ "$REPLY" == 1 ]]; then
? ? ? ? ? ? ? ? echo "Hostname: $HOSTNAME"
? ? ? ? ? ? ? ? uptime
? ? ? ? ? ? ? ? exit
? ? ? ? fi
? ? ? ? if [[ "$REPLY" == 2 ]]; then
? ? ? ? ? ? ? ? df -h
? ? ? ? ? ? ? ? exit
? ? ? ? fi
? ? ? ? if [[ "$REPLY" == 3 ]]; then
? ? ? ? ? ? ? ? if [[ "$(id -u)" -eq 0 ]]; then
? ? ? ? ? ? ? ? ? ? ? ? echo "Home Space Utilization (ALL Users)"
? ? ? ? ? ? ? ? ? ? ? ? du -sh /home/*
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? ? ? echo "Home Space Utilizaion ($USER)"
? ? ? ? ? ? ? ? ? ? ? ? du -sh "$HOME"
? ? ? ? ? ? ? ? fi
? ? ? ? ? ? ? ? exit
? ? ? ? fi
else
? ? ? ? echo "Invalid entry." >&2
? ? ? ? exit 1
fi
第一部分展示了菜單并獲取用戶輸入,第二部分識別輸入并執行相應的菜單項功能。注意腳本中exit命令的用法,在完成用戶選定的功能后,exit可以防止繼續執行不必要的代碼。
原文鏈接:https://blog.csdn.net/weixin_43770382/article/details/127839581
相關推薦
- 2022-11-19 React組件的應用介紹_React
- 2022-11-10 Android開發之AlertDialog實現彈出對話框_Android
- 2022-03-14 Response to preflight request doesn't pass access
- 2022-09-17 Python利用AutoGrad實現自動計算函數斜率和梯度_python
- 2022-03-27 深入理解React?State?原理_React
- 2022-04-02 Docker鏡像發布到Docker?Hub的實現方法_docker
- 2022-09-25 【報錯:No module named pytest】
- 2022-06-22 Python?裝飾器常用的創建方式及源碼示例解析_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支