我正在使用if語句在bash中有多個條件。IF語句的倍數和或條件
如何減少以下行語法。所以從設計的角度看它很好。
if [ "$1" != "-l" ] && [ "$1" != "-a" ] && [ "$1" != "-h" ] && [ "$1" != "" ] && [ "$1" = "-d" ] || [ "$1" = "-mv" ] || [ "$1" = "-dv" ] || [ "$1" = "-mr" ] || [ "$1" = "-dr" ];
由於
我正在使用if語句在bash中有多個條件。IF語句的倍數和或條件
如何減少以下行語法。所以從設計的角度看它很好。
if [ "$1" != "-l" ] && [ "$1" != "-a" ] && [ "$1" != "-h" ] && [ "$1" != "" ] && [ "$1" = "-d" ] || [ "$1" = "-mv" ] || [ "$1" = "-dv" ] || [ "$1" = "-mr" ] || [ "$1" = "-dr" ];
由於
可以創建2個陣列用於匹配和非匹配值,並檢查是否1元件$匹配任何元素陣列中或低於不喜歡的。
nonmatch_array=("-l" "-a" "-h" "")
match_array=( "-d" "-mv" "-dv" "-mr" "-dr")
if [ `echo ${match_array[@]} | grep "$1"` ] || ! [ `echo ${nonmatch_array[@]} | grep "$1"` ] ; then
echo "is in array"
else
echo "is not in array"
fi
希望它能爲你工作。
'grep -q'總是什麼都沒有發出,而''''''''''正在評估你的'...'的stdout作爲一個測試(如果它是一個對測試命令沒有意義的單詞,檢查這個單詞是否是空的;但是用'grep -q',它總是**空的)。 –
@CharlesDuffy:我的壞,不知何故錯過了..更新了答案。感謝您的注意。 –
這裏還有一些改進 - 使用'grep'非常慢;考慮重寫使用關聯數組來執行O(1)時間內的所有進程中的測試。 –
使用模式匹配。
if [[ $1 && $1 != -[lah] && $1 == [email protected](d|mv|dv|mr|dr) ]]; then
@(...)
是擴展模式,這應該是默認在最新版本的bash
被識別內[[ ... ]]
的一個例子。如果您的版本不是最近的版本,請將shopt -s extglob
添加到腳本的開頭。
事實上,你可以刪除$1 && $1 != -[lah]
,因爲它的真理會通過的$1 == [email protected](...)
真相暗示。
if [[ $1 == [email protected](d|mv|dv|mr|dr) ]]; then
你也可以只使用一個符合POSIX標準的case
聲明:
case $1 of
-d|-mv|-dv|-mr|-dr) echo good option ;;
*) echo bad option ;;
esac
首先儘量限制在1行代碼的長度。
if [ [ "$1" != "-l" ]
&& [ "$1" != "-a" ]
&& [ "$1" != "-h" ]
&& [ -n "$1" ]
&& ([ "$1" = "-d" ]
|| [ "$1" = "-mv" ]
|| [ "$1" = "-dv" ]
|| [ "$1" = "-mr" ]
|| [ "$1" = "-dr" ]) ];
我添加了大括號,以明確你的意思是or。現在
你可以用正則表達式將所有的比賽:
if [[ ! ("$a" =~ ^-(l|a|h|d|)$)
&& "$a" =~ ^-(mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
,但是考慮你要測試的。只有當它匹配-mv/-dv/-mr/-dr
時,測試纔會成立,因此您無需測試選件lah
。
if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
您可以使用一個變量,用於提取的選項:
options="d|mv|dv|mr|dr"
if [[ "$a" =~ ^-(${options})$ ]]; then
echo "Yes $a matches"
fi
每次代碼變得難以閱讀(也爲長碼或重複的語句),你應該考慮使用功能。
下一個函數是短暫的,但很難閱讀:
options="d|mv|dv|mr|dr"
function checkoption1 {
[[ "$a" =~ ^-(${options})$ ]]
}
checkoption1 "$a" &&
echo "Yes $a matches"
我會選擇一個稍微更詳細的功能。我將包含您的原始測試lah
以顯示可能性。
# checkoption return 0 for match,
# returns 1 for forbidden option
# returns 2 for undefined option
function checkoption2 {
case "$1" in
-d|-mv|-dv|-mr|-dr) return 0 ;;
-l|-a|-h|"") return 1;;
*) return 2;;
esac
}
checkoption2 "$a" &&
echo "Yes $a matches"
你應該在接受你的代碼之前做一些testruns。
我已經取得了一些測試用小環(現在所有的答案在一起)
function checkoption1 {
[[ "$a" =~ ^-(${options})$ ]]
}
# checkoption return 0 for match,
# returns 1 for forbidden option
# returns 2 for undefined option
function checkoption2 {
case "$1" in
-d|-mv|-dv|-mr|-dr) return 0 ;;
-l|-a|-h|"") return 1;;
*) return 2;;
esac
}
for a in -mv mv -mvx -ms -mr -dr; do
if [[ ! ("$a" =~ ^-(l|a|h|)$)
&& "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then
echo "Yes $a matches"
fi
options="d|mv|dv|mr|dr"
if [[ "$a" =~ ^-(${options})$ ]]; then
echo "Yes $a matches"
fi
checkoption1 "$a" &&
echo "Yes $a matches"
checkoption2 "$a" &&
echo "Yes $a matches 2"
done
如果這是正確的話,我相當肯定的一些是不可移植的 - 比如在嵌套上下文中嵌套'['s'或本地邏輯運算符(例如'&&')。使用'(...)'而不是'{...; }對於分組來說,正在遭受非平凡的效率影響。 –
也許使有效/無效值的列表,然後選擇[檢查,如果該列表確實/不包含'$ 1']( http://stackoverflow.com/questions/8063228/how-do-i-check-if-a-variable-exists-in-a-list-in-bash) –
也許你想使用'getopt'命令來爲你解析命令行選項? –
@ G.Sliepen,[最佳實踐方法](http://mywiki.wooledge.org/BashFAQ/035)不涉及'getopt'。 –