Как подсчитать наиболее встречающуюся последовательность из 3 букв в слове с помощью скрипта bash - PullRequest
3 голосов
/ 13 января 2020

У меня есть образец файла, такой как

XYZAcc
ABCAccounting
Accounting firm
Accounting Aco
Accounting Acompany
Acoustical consultant

Здесь мне нужно найти наиболее часто встречающуюся последовательность из 3 букв в слове

Вывод должен быть

a cc = 5 aco = 3

Возможно ли это в Bash?

Я совершенно не представлял, как я могу выполнить sh с помощью awk, sed, grep.

Любая подсказка, как это возможно ...

PS: нет вывода, потому что я не знаю, как это сделать, я не хочу писать ненужные awk -F, xyz ab c .. ... это никуда не поможет ...

Ответы [ 3 ]

5 голосов
/ 13 января 2020

Вот как начать то, что, я думаю, вы пытаетесь сделать:

$ cat tst.awk
BEGIN { stringLgth = 3 }
{
    for (fldNr=1; fldNr<=NF; fldNr++) {
        field = $fldNr
        fieldLgth = length(field)
        if ( fieldLgth >= stringLgth ) {
            maxBegPos = fieldLgth - (stringLgth - 1)
            for (begPos=1; begPos<=maxBegPos; begPos++) {
                string = tolower(substr(field,begPos,stringLgth))
                cnt[string]++
            }
        }
    }
}
END {
    for (string in cnt) {
        print string, cnt[string]
    }
}

.

$ awk -f tst.awk file | sort -k2,2nr
acc 5
cou 5
cco 4
ing 4
nti 4
oun 4
tin 4
unt 4
aco 3
abc 1
ant 1
any 1
bca 1
cac 1
cal 1
com 1
con 1
fir 1
ica 1
irm 1
lta 1
mpa 1
nsu 1
omp 1
ons 1
ous 1
pan 1
sti 1
sul 1
tan 1
tic 1
ult 1
ust 1
xyz 1
yza 1
zac 1
1 голос
/ 14 января 2020

Это альтернативный метод решения Эд Мортона . Это меньше циклов, но требует немного больше памяти. Идея не в том, чтобы заботиться о пробелах или любых не алфавитных c символах. В конце мы отфильтровываем их.

awk -v n=3 '{ for(i=length-n+1;i>0;--i) a[tolower(substr($0,i,n))]++ }
            END {for(s in a) if (s !~ /[^a-z]/) print s,a[s] }' file

Когда вы используете GNU awk, вы можете сделать это немного по-другому и оптимизировать, задав каждую запись как слово. Таким образом, выбор конца не должен произойти:

awk -v n=3 -v RS='[[:space:]]' '
    (length>=n){ for(i=length-n+1;i>0;--i) a[tolower(substr($0,i,n))]++ }
    END {for(s in a) print s,a[s] }' file
0 голосов
/ 14 января 2020

Это может сработать для вас (GNU sed, sort и uniq):

sed -E 's/.(..)/\L&\n\1/;/^\S{3}/P;D' file |
sort |
uniq -c |
sort -s -k1,1rn |
sed -En 's/^\s*(\S+)\s*(\S+)/\2 = \1/;H;$!b;x;s/\n/ /g;s/.//p'

Используйте первый вызов sed для вывода трехбуквенных строчных слов.

Сортировка слов.

Подсчет дубликатов.

Сортировка отсчетов в обратном числовом порядке с сохранением алфавитного порядка.

Используйте второй вызов sed для манипулирования результатами в нужном формате.


Если вам нужны только строки с дубликатами в алфавитном порядке и в регистре, используйте:

sed -E 's/.(..)/&\n\1/;/^\S{3}/P;D' file |
sort |
uniq -cd |
sed -En 's/^\s*(\S+)\s*(\S+)/\2 = \1/;H;$!b;x;s/\n/ /g;s/.//p
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...