Чтобы посчитать количество совпадений в мега-строке быстро

У меня есть большие текстовые данные без пробелов и без других строк в одной строке. На самом деле, потоки составляют 0,2 Гбит / с, аналогичная ситуация здесь , но в этой задаче подсчет вхождений, которые сложнее вычислительны, чем просто подсчет пустых строк. Матч

585e0000fe5a1eda480000000d00030007000000cd010000 

Пример подмножества данных здесь называется 30.6.2015_data.txt и его полные двоичные данные, называемые 0002.raw . Матч встречается 1 раз в 30.6.2015_data.txt, но 10 раз в полных данных 0002.raw в одной строке. Я подготовил txt-данные по xxd -ps 0002.raw > /tmp/1 && fold -w2 /tmp/1 > /tmp/2 && gsed ':a;N;$!ba;s/\n//g' /tmp/2 > /tmp/3 . Чем быстрее реализация, тем лучше. Чтобы подготовить мега строку в столбце, вы можете использовать этот xxd -ps 0002.raw > /tmp/1 && fold -w2 /tmp/1 > /tmp/2 . Моя текущая ставка составляет 0,0012 с за матч, то есть 0,012 с за десять матчей в полном файле данных, что происходит медленно.

Греп делает это в строках, что невозможно в подсчете. В Vim %s/veryLongThing//gn недостаточно для задачи. Команда wc дает только символ, байт и строки, поэтому не корректирует инструмент, но, вероятно, комбинируя его с чем-то другим. Возможно, сочетание GNU Find и Sed, но все реализации кажутся слишком сложными.

Выводы ответа Mikeserv

 $ cat 1.7.2015.sh time \ ( export ggrep="$(printf '^ \376Z\36\332H \r \3 \a \315\1')" \ gtr='\1\3\a\r\36HZ^\315\332\376' LC_ALL=C gtr -cs "$gtr" ' [\n*]' | gcut -sd\ -f1-6 | ggrep -xFc "$ggrep" ) <0002.raw $ sh 1.7.2015.sh 1 real 0m0.009s user 0m0.006s sys 0m0.007s ----------- $ cat 1.7.2015.sh time \ ( set x58 x5e x20 x20 xfe x5a x1e xda \ x48 x20 x20 x20 x0d x20 x03 x20 \ x07 x20 x20 x20 xcd x01 x20 x20 export ggrep="$(shift;IFS=\\;printf "\\$*")" \ gtr='\0\1\3\a\r\36HXZ^\315\332\376' \ LC_ALL=C i=0 while [ "$((i+=1))" -lt 1000 ] do gcat 0002.raw; done | gtr -cd "$gtr" |gtr 'X\0' '\n ' | gcut -c-23 |ggrep -xFc "$ggrep" ) $ sh 1.7.2015.sh 9990 real 0m4.371s user 0m1.548s sys 0m2.167s 

где все инструменты являются GNU coreutils, и у них есть все опции, которые вы предоставляете в коде. Однако они могут отличаться GNU devtools. Mikeserv запускает свой код 990 раз, и есть 10 событий, поэтому итоговые 9990 событий правильные.

Как вы можете рассчитывать количество матчей в мегаэффекте эффективно?

  • sed, как заменить, когда в строке есть «http: //»?
  • Как удалить строку, если она начинается с. или a> с помощью sed?
  • Задание CRON для выполнения команды с низкой памятью
  • Как я могу автоматически вводить пароль из .bash_profile при запуске команды в качестве sudo?
  • inotifywait - получить старое и новое имя файла при переименовании
  • Удалите строку, используя определенные значения (-)
  • Скрипт должен читать эхо-строку
  • Папки, созданные со сценарием, имеют неправильную измененную метку времени
  • 2 Solutions collect form web for “Чтобы посчитать количество совпадений в мега-строке быстро”

    GNU-реализация grep (также найденная в большинстве современных BSD, хотя последние версии – полная (в основном совместимая) переписывающая), поддерживает опцию -o для вывода всех согласованных частей.

     LC_ALL=C grep -ao CDA | wc -l 

    затем будет подсчитывать все вхождения.

     LC_ALL=C grep -abo CDA 

    чтобы найти их со своим байтовым смещением.

    LC_ALL=C гарантирует, что grep не будет пытаться выполнить некоторый дорогостоящий синтаксический анализ UTF-8 (хотя здесь с фиксированным поиском строк ASCII grep должен иметь возможность оптимизировать синтаксический анализ UTF-8). -a – еще один GNUism, чтобы сказать grep рассмотреть двоичные файлы.

    Поэтому я взял вашу шестую строку и распечатал ее в байтах, но я заменил NULs на <spaces> (в основном потому, что не могу понять, как получить NUL в шаблоне grep ) :

     time \ ( set x58 x5e x20 x20 xfe x5a x1e xda \ x48 x20 x20 x20 x0d x20 x03 x20 \ x07 x20 x20 x20 xcd x01 x20 x20 export grep="$(shift;IFS=\\;printf "\\$*")" \ tr='\0\1\3\a\r\36HXZ^\315\332\376' \ LC_ALL=C i=0 while [ "$((i+=1))" -lt 1000 ] do cat 0002.raw; done | tr -cd "$tr" |tr 'X\0' '\n ' | cut -c-23 |grep -xFc "$grep" ) 

    Переменная tr состоит из восьмеричных escape-последовательностей / символов ASCII для байтовых значений вашей шестнадцатеричной строки, потому что я хотел tr -d elete ее дополнение. Затем я убедился, что самая длинная строка grep может попытаться сопоставить с -c-23 байта с cut и что строка всегда будет возглавлять строку путем tr анслирования X-символов в \n ewlines, а также для замены NUL для <пробелов >.

    Я кочую сырую двоичную систему на конвейере 999 раз здесь. Поскольку в файле 10 совпадений, результаты:

     9990 1.06s user 0.94s system 65% cpu 3.054 total 

    Теперь я также тестировал …

     time \ ( set x58 x5e x20 x20 xfe x5a x1e xda \ x48 x20 x20 x20 x0d x20 x03 x20 \ x07 x20 x20 x20 xcd x01 x20 x20 export LC_ALL=C i=0 grep="$(IFS=\\;printf "\\$*")" while [ "$((i+=1))" -lt 1000 ] do cat 0002.raw; done | tr '\0 ' ' \0' | grep -aFo "$grep"| wc -l ) 

    Я использую wc -l там, но в моих тестах, похоже, не было никакого разного времени, чтобы использовать -caFo и вообще отказаться от wc . Во всяком случае, подсчеты были одинаковыми. Результаты для этого:

     9990 1.56s user 1.46s system 82% cpu 3.648 total 

    Теперь эти два набора команд не эквивалентны. Хотя, похоже, он немного ускоряется, сначала вытесняя ненужные байты w / tr , но это означает, что вы можете получить счет, вы не можете получить смещения, как вы могли бы, добавив -b переключатель в grep во второй пример…

     time \ ( set x58 x5e x20 x20 xfe x5a x1e xda \ x48 x20 x20 x20 x0d x20 x03 x20 \ x07 x20 x20 x20 xcd x01 x20 x20 export LC_ALL=C i=0 grep="$(IFS=\\;printf "\\$*")" while [ "$((i+=1))" -lt 1000 ] do cat 0002.raw; done | tr '\0 ' ' \0' | grep -baFo "$grep" | sed -nl ) 

     ... 241133568:X^ \376Z\036\332H \r \003 \a \315\001 $ 241157720:X^ \376Z\036\332H \r \003 \a \315\001 $ 241181872:X^ \376Z\036\332H \r \003 \a \315\001 $ 241206024:X^ \376Z\036\332H \r \003 \a \315\001 $ 241230176:X^ \376Z\036\332H \r \003 \a \315\001 $ 241254328:X^ \376Z\036\332H \r \003 \a \315\001 $ 1.59s user 1.41s system 85% cpu 3.496 total 

    И так, что вы выбираете, я думаю, будет зависеть от того, что вы хотите. Для просто счет, возможно, tr -cd будет лучше – он надежно завершает половину секунды быстрее, чем другой каждый раз, но это не так много, и, возможно, если ваш grep будет поддерживать его, grep -baFo может быть что вам нужно.

    Linux и Unix - лучшая ОС в мире.