任務
這裡的參數是檔名!該文件包含文字。腳本的任務是確定哪個單字最常包含(換句話說)。
輸入和輸出範例
(例如,文本是:打球、足球、籃球、雪球 - 因此球是贏家,因為它是其他三個世界的一部分)。
到目前為止我的程式碼
到目前為止我已經完成了這段程式碼,但它並不適用於每個輸出
!/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}"
。