Bash

將布爾比較中的值分配給變數

  • September 28, 2022

我有一個腳本,我需要在其中對字元串變數的內容進行所有可能的比較。每種組合都需要對變數內容採用不同的方法,因此如下所示:

if $a contains "a" AND "b" AND "c"; then do x
elif $a contains "a" AND "b" but NOT "c"; then do y
elif $a contains "b" AND "c" but NOT "a"; then do z
...

據我所知,這樣做的方法是構造一個像這樣的 if 條件:

if [[ $A == *"b"* ]] && [[ $A == *"c"* ]] && [[ $A == *"d"* ]]
elif [[ $A == *"b"* ]] && [[ $A == *"c"* ]]
elif [[ $A == *"c"* ]] && [[ $A == *"d"* ]]
elif [[ $A == *"b"* ]] && [[ $A == *"d"* ]]
elif [[ $A == *"b"* ]]
elif [[ $A == *"c"* ]]
elif [[ $A == *"d"* ]]
fi

但這當然太複雜了,因為我的變數($A)和子字元串(b,c,d)的名稱比這長得多。所以我想看看是否有辦法將條件表達式的內容保存到變數中:

contains_b= *a condition for [[ $A == *"b"* ]]*; echo $contains_b-> 真 | 錯誤的

我只在這裡找到了回复[ contains_b=$(! [ "$A" = *"b"* ]; echo $?)]; 但是,$contains_b -> 0在隨後的條件句中不起作用,因為:

if $contains_b; then do x; fi->bash: [0]: command not found

所以我能想到的唯一解決方案是手動完成:

if [[ $A == *"b"* ]]; then
   contains_b=true
else
   contains_b=false
fi

但是,我最終會執行三個 if 語句來獲取三個變數,以及每個不同組合的其他 7 個比較。

我想知道是否有不同/更有效的方法。如果沒有,您對進行這些多重比較的另一種方法有什麼建議嗎?我覺得我把它弄得太複雜了……

感謝您的任何幫助。

創建一個二進制遮罩,然後對其進行操作。這樣做的好處是每個測試只執行一次,並將測試與對測試結果的操作分開。

請注意,程式碼將模式用作擴展的正則表達式。要將它們作為字元串進行比較,請使用

[[ $string == *"$pattern"* ]]

代替

[[ $string =~ $pattern ]]

在下面的程式碼中。

patterns=( a b c )
string='abba'

mask=0; i=0
for pattern in "${patterns[@]}"; do
       if [[ $string =~ $pattern ]]; then
               # setting the i:th bit from the right to one
               mask=$(( mask | (1 << i) ))
       fi
       i=$(( i + 1 ))
done

case $mask in
       0) echo no match ;;
       1) echo first pattern matched ;;
       2) echo second pattern matched ;;
       3) echo first and second pattern matched ;;
       4) echo third pattern matched ;;
       5) echo first and third pattern matched ;;
       6) echo second and third pattern matched ;;
       7) echo all patterns matched ;;
       *) echo error
esac

或者,使用帶有 1 和 0 的字元串遮罩(0 表示不匹配,1 表示匹配)。請注意,mask下面的字元串與上面程式碼中使用的數字的實際二進製表示相反。

patterns=( a b c )
string='abba'

unset -v mask
for pattern in "${patterns[@]}"; do
       ! [[ $string =~ $pattern ]]
       # string concatenation of the exit status of the previous command
       mask+=$?
done

case $mask in
       000) echo no match ;;
       100) echo first pattern matched ;;
       010) echo second pattern matched ;;
       110) echo first and second pattern matched ;;
       001) echo third pattern matched ;;
       101) echo first and third pattern matched ;;
       011) echo second and third pattern matched ;;
       111) echo all patterns matched ;;
       *) echo error
esac

每個腳本的輸出將是

first and second pattern matched

…因為字元串abba匹配前兩個模式,a並且b.

引用自:https://unix.stackexchange.com/questions/718976