任務

任務

任務

這裡的參數是檔名!該文件包含文字。腳本的任務是確定哪個單字最常包含(換句話說)。


輸入和輸出範例

(例如,文本是:打球、足球、籃球、雪球 - 因此球是贏家,因為它是其他三個世界的一部分)。


到目前為止我的程式碼

到目前為止我已經完成了這段程式碼,但它並不適用於每個輸出

!/bin/sh
awk '{for(i=2;i<NF;i++) {s=$i; for(j=i+1;j<=NF;j++) print s=s FS $j}}' $1 | sort | uniq -c | sort -k1,1rn -k2 | sed 's/ *[^ ]* *//;q' | cut -f1 -d" "

答案1

如果單字清單位於名為 的檔案中words,每行只有一個單字(可能是使用 來tr ' ' '\n' <originalwords >words將原始清單拆分為多行而建立的),則循環

while IFS= read -r word; do
    grep -F -o -e "$word" words
done <words | awk '{ c[$0]++; if (c[$0] > c[w]) w = $0 } END { print w }'

將輸出出現次數最多的單字作為清單中單字的一部分(或者,如果許多單字出現相同次數,則輸出清單中第一個出現的單字)。

它透過使用列表本身作為一組模式來與列表進行匹配來實現此目的。我們-o要求在單獨的行上傳回符合的子字串。

單獨循環的輸出以及問題中給出的列表將是

play
ball
ball
ball
ball
football
basketball
snowball

然後只需計算這些單字並選擇最常出現的單字即可。


作為一個完整的腳本,具有臨時文件處理:

#!/bin/sh

tmpfile=$(mktemp)

trap 'rm -f "$tmpfile"' EXIT      # delete temporary file upon exiting

tr -s ' ' '\n' <"${1:-/dev/stdin}" >"$tmpfile"  # convert into word list

while IFS= read -r word; do
    grep -F -o -e "$word" "$tmpfile"
done <"$tmpfile" | awk '{ c[$0]++; if (c[$0] > c[w]) w = $0 } END { print w }'

如果沒有指定文件,則該腳本也會從標準輸入中讀取。

答案2

awk '{
        for (i=1; i<=NF; i++) {
                uwords[$i] = 0
                allwords[++idx] = $i
        }
     }
    END {
                if (idx == 0) exit
                max = 0
                for (w in uwords) {
                        count = 0
                        for (i=1; i<=idx; i++) {
                                if (allwords[i] ~ w) count++;
                        }
                        if (count > max) {
                                max = count
                                maxw = w
                        }
                }
                print maxw
        }'

掃描輸入並提取唯一單字清單和所有單字清單。 (我想我們不需要唯一單詞的列表,但在輸入較大的情況下它可能會使事情變得更有效。)然後,對於每個唯一單詞,計算文件中有多少單詞與其匹配。 (因此,如果檔案包含football football football,則 向 計數 3。ball)追蹤符合最多的那個。

uwords如果出現平局,它會報告(唯一單字)數組中第一個出現的單字。這不一定是文件中出現的第一個,也不是按字母順序排列的第一個。

如果任何單字包含,這可能會產生意想不到的結果.*或者[


如果您喜歡 Kusalananda 的 shell+awk 方法,但不希望出現邊緣狀況錯誤,請執行以下操作:

tmpfile=$(mktemp)

trap 'rm -f "$tmpfile"' EXIT      # delete temporary file upon exiting

tr -s ' ' '\n' < "${1:-/dev/stdin}" > "$tmpfile"  # convert into word list

sort -u "$tmpfile" | while IFS= read -r word
do
    grep -F -o -e "$word" "$tmpfile"
done | awk '{ c[$0]++; if (c[$0] > c[w]) w = $0 } END { print w }'

透過對單字列表進行排序,我們得到了唯一單字的列表,因此不會對任何單字進行多次計數。

請注意,此程式碼明確假設最多有一個輸入檔(但可能沒有檔案;即從 stdin 讀取)。這與問題的措詞是一致的。但是,如果可能有任意數量的輸入檔(零、一、或更多),將該tr行更改為

cat -- "$@" | tr -s ' ' '\n' > "$tmpfile"         # convert into word list

可以說這是一個 UUOC,但是

  • 它處理兩個或多個輸入檔的情況,並且
  • 它比 . 更具可讀性< "${1:-/dev/stdin}"

相關內容