найти наиболее часто встречающиеся комбинации букв/символов в файле

Если приказ шаблонов фиксирован, вы можете легко использовать GREP , как в:

grep -E 'pattern1.*pattern2.*pattern3'

, но в случае, если все шаблоны должны присутствовать, и они могут появиться в любой заказ, затем вы получаете комбинаторную сложность; например Для двух шаблонов:

grep -E '(pattern1.*pattern2|pattern2.*pattern1)'

(и для трех узоров у вас уже есть восемь комбинаций).

В таких случаях (т. Е. При использовании GREP ) лучше каскадные вызовы в трубопроводе одного GREP на рисунок:

grep pattern1 <infile | grep pattern2 | grep pattern3

каждый экземпляр фильтрует только линии Это соответствует их шаблону, и общий результат будет содержать только строки, которые имеют все шаблоны.

Лучший подход, который приводит к чистому решению, заключается в использовании :

awk '/pattern1/ && /pattern2/ && /pattern3/'

, где упорядочение не имеет значения в таком выражении.

-1
13.04.2017, 15:36
4 ответа

Любая комбинация, при условии как минимум двух (как минимум N изменение {2, $ l} to {N, $ l} ), игнорируя регистр для каждой строки, можно сделать что-то вроде

% < examplelist 
Stack
Exchange
Internet
Web
Question
Find
Frequent
Words
Combination
Letters
% < examplelist perl -nlE '$_=lc; $l=length; next if $l < 2; m/(.{2,$l})(?{ $freq{$1}++ })^/; END { say "$freq{$_} $_" for keys %freq }' | sort -rg | head -4
3 in
2 ue
2 tion
2 tio
1
28.01.2020, 05:09

Вот сценарий Perl, который сортирует вывод по вхождению. Минимальная длина строки настраивается и включает параметр отладки, чтобы увидеть, что происходит.

#!/usr/bin/perl
# Usage: perl script_file input_file

use strict;
my $min_str_len = 2;
my $debug = 0;

my %uniq_substrings;

while(<>)
{
    chomp;
    my $s = lc $_; # assign to $s for clearity

    printf STDERR qq|#- String: [%s]\n|, $s if $debug;
    my $line_len = length($s);
    for my $len ($min_str_len .. $line_len)
    {
        printf STDERR qq|# Length: %u\n|, $len if $debug;
        # break string into characters
        my @c  = split(//,$s);
        # iterate over list while large enough to provide strings of $len characters
        while(@c>=$len)
        {
            my $substring = join('', @c[0..$len-1]);
            my $curr_count = ++$uniq_substrings{$substring};
            printf STDERR qq|%s (%s)\n|, $substring, $curr_count if $debug;
            shift @c;
        }
    }
}

sub mysort
{
    # sort by count, subsort by alphabetic
    my $retval =
        ($uniq_substrings{$b} <=> $uniq_substrings{$a})
        || ($a cmp $b);
    return $retval;
}

for my $str (sort(mysort keys %uniq_substrings))
{
    printf qq|%s = %u\n|, $str, $uniq_substrings{$str};
}
0
28.01.2020, 05:09

Мне нужно перечислить все повторяющиеся строки комбинации букв...

...поэтому я заставил скрипт просмотреть все возможные длины от 1 буквы до полной длины строки (что является длиной слова, потому что образец данных подает 1 слово в строку)....

Файл ssf.mawk:

#!/usr/bin/mawk -f
BEGIN {
        FS=""
}
{
        _=tolower($0)
        for(i=1;i<=NF;i++)
                for(j=i;j<=NF;j++)
                        print substr(_,i,j-i+1) | "sort|uniq -c|sort -n"
}

Сокращённый вывод выполнения с вашим выборочным вводом:

$ printf '%s\n' Stack Exchange Internet Web Question Find Frequent Words Combination Letters .... | ./ssf.mawk
      1 ....
      1 ac
      1 ack
      1 an
      1 ang

(((здесь опущено много строк))

      4 s
      5 i
      8 n
      8 t
     10 e

Я протестировал это с помощью mawk-1.3.3 и gawk-4.1.1 на Debian8.

1
28.01.2020, 05:09

Сценарий:

MIN=2
MAX=5
while read A; do
    [ ${MAX} -lt ${#A} ] && max=${MAX} || max=${#A}
    for LEN in $(seq ${MIN} ${max}); do
        for k in $(seq 0 $((${#A}-${LEN}))); do
            echo "${A:$k:${LEN}}"
        done
    done
done <<< "$(cat file1|tr 'A-Z' 'a-z')" |sort|uniq -c|sort -k1,7rn -k9

С небольшими пояснениями:

# define minimal length of letters combinations
MIN=2
# define maximal length of letters combinations
MAX=5
# take line by line
while read A; do
    # determine max length of letters combination for this line
    # because it is shorter than MAX above if length of the line is shorter
    [ ${MAX} -lt ${#A} ] && max=${MAX} || max=${#A}
    # in cycle take one by one possible lengths of letters combination for line
    for LEN in $(seq ${MIN} ${max}); do
        # in cycle take all possible letters combination for length LEN for line
        for k in $(seq 0 $((${#A}-${LEN}))); do
            # print a letter combination
            echo "${A:$k:${LEN}}"
        done
    done
done <<< "$(cat file1|tr 'A-Z' 'a-z')" |sort|uniq -c|sort -k1,7rn -k9
# the data are taken from file "file1" and converted to lowercase,
# the data are sorted, unique lines counted,
# after results sorted according to string numerical values for numbers
# and strings with the same numbers sorted in alphabetical order

Вывод первых 30 строк, если параметры MIN=2 и MAX=5 (Всего на выходе 152 строки):

      3 in
      2 er
      2 et
      2 io
      2 ion
      2 nt
      2 on
      2 qu
      2 que
      2 st
      2 te
      2 ter
      2 ti
      2 tio
      2 tion
      2 ue
      1 ac
      1 ack
      1 an
      1 ang
      1 ange
      1 at
      1 ati
      1 atio
      1 ation
      1 bi
      1 bin
      1 bina
      1 binat
      1 ch
     ...

Вывод первых 20 строк, если параметры MIN=1 и MAX=3 (Всего на выходе 109 строк):

     10 e
      8 n
      8 t
      5 i
      4 o
      4 r
      4 s
      3 a
      3 c
      3 in
      2 b
      2 d
      2 er
      2 et
      2 f
      2 io
      2 ion
      2 nt
      2 on
      2 q
     ...
0
28.01.2020, 05:09

Теги

Похожие вопросы