Замените несколько строк в единственной передаче

Не давайте интерфейсу IP-адрес. Просто поднимите его и получите пакеты с libpcap. Если это не будет иметь никакого IP-адреса, то ядро оставит его в покое, если это будет Вашим беспокойством.

Если Вы хотите, чтобы интерфейс обработал IP-адрес ядром и перенаправил только некоторые пакеты IP к Вашему приложению, netfilter может сделать это. Посмотрите на NFQUEUE или NFLOG iptables цель.

Если выполнение захвата пакетов является Вашим беспокойством, взгляд на PF_RING.

Иначе возможно, можно объяснить более подробно, что Вы пытаетесь сделать, поскольку это неясно мне.

11
19.06.2014, 01:51
3 ответа

решение perl. Даже если некоторые из них не могут быть указаны, это невозможно, Я нашел одну, но в целом простой матч и замена невозможны, и даже хуже из-за отставания NFA результат может быть неожиданным.

В общем, и это надо сказать, проблема дает разные результаты, которые зависят от порядка и длины кортежей замены, т.е.:

A B
AA CC

и вход AAA дает результат в BBB или CCB.

Здесь код:

#!/usr/bin/perl

$v='if (0) {} ';
while (($a,$b)=split /\s+/, <DATA>) {
  $k.=$a.'|';
  $v.='elsif ($& eq \''.$a.'\') {print \''.$b.'\'} ';
}
$k.='.';
$v.='else {print $&;}';

eval "
while (<>) {
  \$_ =~ s/($k)/{$v}/geco;
}";  
print "\n";


__DATA__
A    B
B    A
abba baab
baab abbc
abbc aaba

Checkerbunny:

$ echo 'ABBabbaBBbaabAAabbc'|perl script
$ BAAbaabAAabbcBBaaba
1
27.01.2020, 19:58

Хорошо, общее решение. Следующая функция bash требует 2k аргументов; каждая пара состоит из заполнителя и замены. Вы должны заключить строки в соответствующие кавычки, чтобы передать их функции. Если количество аргументов нечетное, будет добавлен неявный пустой аргумент, который эффективно удалит вхождения последнего заполнителя.

Ни заполнители, ни замены не могут содержать символы NUL, но вы можете использовать стандартные C \ -экраны, такие как \ 0 , если вам нужны NUL s (и следовательно, вам необходимо написать \\ , если вы хотите \ ).

Для этого требуются стандартные инструменты сборки, которые должны присутствовать в posix-подобной системе (lex и cc).

replaceholder() {
  local dir=$(mktemp -d)
  ( cd "$dir"
    { printf %s\\n "%option 8bit noyywrap nounput" "%%"
      printf '"%s" {fputs("%s", yyout);}\n' "${@//\"/\\\"}"
      printf %s\\n "%%" "int main(int argc, char** argv) { return yylex(); }"
    } | lex && cc lex.yy.c
  ) && "$dir"/a.out
  rm -fR "$dir"
}

Мы предполагаем, что \ уже экранирован, если необходимо, в аргументах но нам нужно избегать двойных кавычек, если они есть. Вот что второй аргумент для второго printf делает. Поскольку действие по умолчанию lex - ECHO , нам не нужно об этом беспокоиться.

Пример выполнения (с таймингом для скептиков; это просто недорогой серийный ноутбук):

$ time echo AB | replaceholder A B B A
BA

real    0m0.128s
user    0m0.106s
sys     0m0.042s
$ time printf %s\\n AB{0000..9999} | replaceholder A B B A > /dev/null

real    0m0.118s
user    0m0.117s
sys     0m0.043s

Для больших входных данных может быть полезно предоставить флаг оптимизации для cc , а для текущего Posix совместимость, лучше было бы использовать c99 . Еще более амбициозная реализация может пытаться кэшировать сгенерированные исполняемые файлы вместо того, чтобы каждый раз их генерировать, но их создание не совсем дорогое.

Правка

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

treplaceholder () { 
  tcc -run <(
  {
    printf %s\\n "%option 8bit noyywrap nounput" "%%"
    printf '"%s" {fputs("%s", yyout);}\n' "${@//\"/\\\"}"
    printf %s\\n "%%" "int main(int argc, char** argv) { return yylex(); }"
  } | lex -t)
}

$ time printf %s\\n AB{0000..9999} | treplaceholder A B B A > /dev/null

real    0m0.039s
user    0m0.041s
sys     0m0.031s
10
27.01.2020, 19:58
printf 'STRING1STRING1\n\nSTRING2STRING1\nSTRING2\n' |
od -A n -t c -v -w1 |
sed 's/ \{1,3\}//;s/\\$/&&/;H;s/.*//;x
     /\nS\nT\nR\nI\nN\nG\n1/s//STRING2/
     /\nS\nT\nR\nI\nN\nG\n2/s//STRING1/
     /\\n/!{x;d};s/\n//g;s/./\\&/g' |
     xargs printf %b

###OUTPUT###

STRING2STRING2

STRING1STRING2
STRING1

Что-то вроде этого всегда будет заменять каждое вхождение ваших целевых строк только один раз, как они встречаются в sed в потоке, по одному биту на строку. Я могу представить, что это самый быстрый способ сделать это. Опять же, я не пишу C. Но этот действительно надежно обрабатывает нулевые разделители, если вы этого хотите. См. этот ответ , чтобы узнать, как это работает. У этого нет проблем с любыми содержащимися в нем специальными символами оболочки или подобными, но он зависит от локали ASCII, или, другими словами, od не будет выводить многобайтовые символы в одной строке и сделаю только один за. Если это проблема, вы можете добавить в iconv .

1
27.01.2020, 19:58

Теги

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