В дистрибутивах на основе Debian, как и в Ubuntu, вы можете найти и загрузить исходный код, как показано ниже:
$ which man
/usr/bin/man
$ dpkg --search /usr/bin/man
man-db: /usr/bin/man
$ apt-get source man-db
Это поместит исходный код в ваш текущий рабочий каталог.
Если список слов находится в файле с именем 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 }'
Скрипт дополнительно читает из стандартного ввода, если файл не указан.
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
(уникальных слов ). Это не обязательно первое, что появляется в файле, и не первый в алфавитном порядке.
Это может привести к неожиданным результатам. если какое-либо из слов содержит .
, *
или [
.
Если вы предпочитаете подход Кусалананды 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 }'
Сортируя список слов, мы получаем список уникальных слов, и, таким образом, не считать слова несколько раз.
Обратите внимание, что этот код явно предполагает что существует не более одного входного файла (но файла могло и не быть; т. е. читать со стандартного ввода ). Это соответствует формулировке вопроса. Однако,если может быть любое количество входных файлов (ноль, один, или более ), измените строку tr
на
cat -- "$@" | tr -s ' ' '\n' > "$tmpfile" # convert into word list
Возможно, это UUOC, но
< "${1:-/dev/stdin}"
.