測試字串數組中是否存在字串

測試字串數組中是否存在字串

我正在編寫一個腳本,它將文件中每行的前 3 個字母(透過使用 cut 來獲取它們)與數組中的字串進行比較。我已經環顧四周,但我找到的解決方案不適用於我的系統。

現在看起來像這樣:

weekdays=([Mon]=1 [Tue]=1 [Wed]=1 [Thu]=1 [Fri]=1 [Sat]=1 [Sun]=1)
input="/Foo/Bar.log"

while read -r line
do

cutline="$(echo ${line} | cut -c 1-3"

if [[ ${weekdays["$cutline"]} ]]
then
echo "Match"
else
echo "No Match"
fi

done < ${input}

該線被正確切斷,但測試期間的某些內容會返回誤報,因為無論前 3 個字母是什麼,它都會返回「匹配」。

當我使用 -x 檢查腳本時,它向我展示了,而不是它使用的實際測試

[[ -n 1 ]]

當我用表達式測試它時,[ ]它顯示了1

它是否檢查數組中的每個字符而不僅僅是整個單詞,或者是否還有其他問題?

如果沒有問題,是否有另一種方法可以將一行的前 3 個字母與數組中的所有字母進行比較,然後再繼續下一個字母?

附帶說明:我確實正在運行 Bash 4,所以關聯數組應該可以工作

答案1

基本錯誤是您實際上並未聲明關聯數組:

$ weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1)
$ echo ${weekdays[@]}
1
$ echo ${weekdays[0]}
1
$ echo ${weekdays[2]}

$

我不完全確定 bash 如何處理它以及為什麼它只需要一個1,但我確信這不是一個關聯數組。正如man bash(強調我的)中所解釋的:

如果使用語法 name[下標]=value 指派任何變量,則會自動建立索引數組。下標被視為必須計算為數字的算術表達式。若要明確宣告索引數組,請使用declare -a name(請參閱下方的SHELL BUILTIN指令)。聲明 -a name[下標] 也被接受;下標被忽略。

關聯數組是使用聲明 -A 名稱建立的。

因此,請嘗試這樣做,它將按您的預期工作:

declare -A weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1)

也就是說,您的腳本比您需要的要複雜一些。這是使用相同方法的更簡單的版本:

#!/bin/bash
declare -A weekdays=(["Mon"]=1 ["Tue"]=1 ["Wed"]=1 ["Thu"]=1 ["Fri"]=1 ["Sat"]=1 ["Sun"]=1)
input="/Foo/Bar.log"

cut -c 1-3 "$input" | while read -r line; do
    if [[ ${weekdays["$line"]} ]]
    then
            echo "Match : $cutline : ${weekdays[$line]}"
    else
            echo "No Match"
    fi
done    

雖然我可能會這樣做:

#!/bin/bash
cut -c 1-3 "$1" | while read -r line; do
        case $line in
        "Mon"|"Tue"|"Wed"|"Thu"|"Fri"|"Sat"|"Sun")
                        echo yes;;
                *)
                        echo no;;
        esac
done

然後,使用目標檔案名稱作為參數來執行腳本:

script.sh /Foo/Bar.log"

答案2

我會使用一次文本處理工具的呼叫來處理文本,不是每行輸入都有幾個工具:

awk -v 'weekday=(Mon|Tue|Wed|Thu|Fri|Sat|Sun)' '
  {print ($0 ~ "^" weekday ? "" : "No ") "Match"}' < "$input"

如果您需要為輸入的每一行運行特定的應用程序,則可以使用循環,但如果只是文字處理(例如將行輸出到某個文件),則awk可以這樣做:

awk -v 'weekday=Mon|Tue|Wed|Thu|Fri|Sat|Sun' '
  (day = substr($0, 1, 3)) ~ weekday {
    print substr($0, 4) > day ".txt"
  } < "$input"

相關內容