![bash腳本檢查輸入是否有@](https://rvso.com/image/1048309/bash%E8%85%B3%E6%9C%AC%E6%AA%A2%E6%9F%A5%E8%BC%B8%E5%85%A5%E6%98%AF%E5%90%A6%E6%9C%89%40.png)
您好,我正在嘗試編寫一個 bash 腳本,其中檢查輸入以查看它是否包含 @ 符號,我對 bash 比較陌生,所以請原諒任何/所有錯誤!到目前為止我有:
var1="@"
var2="INPUT"
echo "input"
read INPUT
if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi
答案1
儘管您可以選擇使用內建的 shell 功能來檢查使用者的輸入是否包含@
(其他答案中有詳細記錄),但另一種合理的方法是使用外部grep
公用事業:
#!/usr/bin/env bash
read -erp '> '
if grep -q @ <<<"$REPLY"; then
echo pass
else
echo fail
fi
傳遞-q
標誌以grep
防止它列印匹配的行。 (它還可以防止它在找到匹配項後讀取更多行,但這並沒有什麼區別,因為只有一行輸入。)
if
將構造縮短為類似的東西很誘人grep -q @ <<<"$REPLY" && echo pass || echo fail
,但我故意避免這樣做:
- 在這種情況下,這可能沒問題,因為列印錯誤單字的唯一方法是如果
pass
應該列印但echo
未能列印它。那麼,echo 可能fail
也無法列印。 - 雖然短路
&&
和||
通常本身是合適的(我經常使用它們來縮寫if
沒有一個else
子句),將它們一起使用,就好像它們是三元如果操作員這確實不是一個好習慣。雖然有些命令不能失敗,echo
能。 - 如果用戶重定向您的腳本的輸出到不可寫入的檔案或設備,或在損壞的情況下使用它管道、echo 等輸出文字的命令可能會傳回失敗,導致表達式失敗並執行表達式
&&
的右側。||
- 您可以透過使用 執行腳本來測試腳本在存在不可寫入輸出裝置的情況下的行為
>/dev/full
。
腳本使用了一些 bash 功能:
-e
啟用 GNU readline,因此使用者可以使用箭頭鍵左右移動遊標以在輸入時編輯輸入。- 在 bash 中,如果沒有給出變量,則
read
自動將使用者的輸入放入變數中。REPLY
- A這裡的字串with
<<<
是將使用者輸入傳遞給 的便捷方法grep
。 - 重擊和一些其他 Bourne 風格的 shell,例如 dash 接受
-p
.但POSIX 相容的 shell 只需要了解-r
。在某些(例如 ksh)中,-p
具有不同的意義。
(謝謝蓋爾哈指出這兩點-p
有時缺席然後它並不總是意味著“及時”。)
如果您想要一個可移植到可能未安裝 bash 的其他作業系統的腳本,您可以使用:
#!/bin/sh
printf '> '
read -r line
if printf '%s' "$line" | grep -q @; then
echo pass
else
echo fail
fi
如果您願意,您可以透過讀取使用者的輸入來跳過將使用者的輸入儲存在變數中head
代替read
:
#!/bin/sh
printf '> '
if head -1 | grep -q @; then
echo pass
else
echo fail
fi
作為蓋爾哈提到,可能被認為是head -n 1
更好的語法head -1
正式過時(儘管當前的sed
實現,或至少是 GNU sed,-1
在其最新版本中支持,而一些非常舊的sed
實現不支持-n 1
)。
作為head
文件說,您可以使用sed
它來獲得最大的便攜性。
#!/bin/sh
printf '> '
if sed 1q | grep -q @; then
echo pass
else
echo fail
fi
答案2
此bash
代碼讀取輸入並在輸入包含符號時發出“通過”信號@
:
read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail
筆記:
[ "$var" ]
是一個 bash 測試。如果字串$var
非空, 則傳回 true 。bash 的功能之一是模式替換。看起來像
${var//pattern/string}
。它將每次出現的pattern
in替換var
為string
。在我們的例子中,pattern
is[^@]
是一個符合每個字元的正規表示式除了@
。因此${var//[^@]/}
傳回一個空字串,除非var
至少包含一個@
。我們將上面兩者結合起來:
[ "${var//[^@]/}" ]
僅當
${var//[^@]/}
為非空時,此測試才會成功,且僅當包含至少一個時,此測試${var//[^@]/}
才為非空。var
@
使用顯式的 if-then-else:
read -p "Input: " var
if [ "${var//[^@]/}" ]
then
echo Pass
else
echo Fail
fi
POSIX 外殼
以下內容在dash
( /bin/sh
) 下工作並且應該在任何 POSIX shell 下工作:
printf "Input: "
read var
case "$var" in
*@*) echo Pass
;;
*) echo Fail
;;
esac
POSIX shell 不支援-p
下列選項read
。因此,使用printf
和的組合read
來代替。此外,由於缺乏 的高階變數擴充功能bash
,此case
語句可用於全域匹配。
安卓外殼
使用我的 Android 上的預設 shell,可以執行以下操作:
echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
echo Pass
else
echo Fail
答案3
bash 中的首選方法是使用 的模式匹配功能[[ ... ]]
。
#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
printf '<%s> contains @\n' "$input"
fi
對於sh
腳本,您可以case
改為使用。
#sh
printf 'Input: '
read -r input
case $input in
*@*) printf '<%s> contains @\n' "$input" ;;
esac
另請參閱測試和條件Bash 指南的章節。
答案4
在較新版本的 bash 中,您應該能夠使用正規表示式匹配透過=~
擴展測試運算符:
$ read -p "input: " input
input: quertyuiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
no match
$
$ read -p "input: " input
input: qwerty@uiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
match
應該在任何 POSIX 相容系統中工作的替代方法是在 shell 中使用expr
例如dash
:
$ read input
qwertyuiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
no match
$
$ read input
qwerty@uiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
match
$