The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Как в Perl оптимально заменить символы в строке или разбить строку на части
При работе с большими строками нужно избегать внутреннего копирования строк, 
которое происходит при использоании регулярных выражений или оператора split.

Для разбиеная строки вида "small_begin:big_end" на две подстроки используем:
   my $pos=index($str, ':');
   my $begin_str = substr($str, 0, $pos,""); 
   # в $str остается только big_end часть, в $begin_str - "small_begin:"

Соответсвенно, для замены символов удобно использовать:
    substr(строка, начало замены, число заменяемых символов, блок на который заменяем);
 
30.11.2004
Ключи: perl, string / Лицензия: CC-BY
Раздел:    Корень / Программисту и web-разработчику / Perl / Переменные в Perl

Обсуждение [ RSS ]
  • 1.1, bm (??), 15:00, 30/11/2004 [ответить]  
  • +/
    А не удобнее ли использовать для замены регулярные выражения вроде:
    $str =~ s/h/j/g;

    Заменит во всей строке символы h на j.

     
  • 1.2, Игорь (??), 06:34, 02/12/2004 [ответить]  
  • +/
    разбить или выделить:
    ($str1, $str2, str3 ...) = split (":", $string);
    замена:
    $string =~ s/xaker/maker/g;
     
     
  • 2.3, Maxim Chirkov (ok), 09:32, 02/12/2004 [^] [^^] [^^^] [ответить]  
  • +/
    >разбить или выделить:
    >($str1, $str2, str3 ...) = split (":", $string);

    Господа, речь идет про исключение лишних копирований в памяти. На досуге, возмите  в качестве $string строку размером несколько Мб и посмотрите сколько будет занимать процесс perl в памяти после split и "=~" (кстати сказать, простейшие замены с совпадением размера память лишнюю не потребляют).


     
     
  • 3.4, Игорь (??), 06:45, 03/12/2004 [^] [^^] [^^^] [ответить]  
  • +/
    При таких объемах это естественно.
    Perl для небольших объемов расчитывался.
    Выход: написать на си подпрограмму или скомпилить скрипт в бинарник
    perl2bin
     
     
  • 4.6, Maxim Chirkov (ok), 10:40, 03/12/2004 [^] [^^] [^^^] [ответить]  
  • +/
    >При таких объемах это естественно.
    >Perl для небольших объемов расчитывался.

    Лишние копирования сильно паразитируют в циклах и для маленьких строк.

    >Выход: написать на си подпрограмму

    Не всегда критический участок поддается такому преобразованию, когда напирмер, используются хэши или регекпсы.

    > или скомпилить скрипт в бинарник perl2bin

    При цикличных операциях выйгрыша не будет, так как скрипт уже переведен в псевдокод.


     
  • 4.8, achmed (??), 15:57, 13/12/2004 [^] [^^] [^^^] [ответить]  
  • +/
    даже если писать на компилируемом языку (например Си),
    скорость при использовании регулярных выражений (библиотек
    много разных) будет медленнее чем при использовании
    стандартных функций для работы со строками, за удовство
    приходится платить скоростью.
     

  • 1.5, agility_member (?), 09:11, 03/12/2004 [ответить]  
  • +/
    а awk или sed ?
     
  • 1.7, mic (??), 07:17, 09/12/2004 [ответить]  
  • +/
    Где-то недавно видел статейку на английском про оптимизацию этого процесса. Щас уже не найду, но скриптик оттуда (переделанный слегка) вот:

    ---------------------------------------------
    #!/usr/bin/perl

    my $URI = "http://www.stonehenge.com/merlyn/" .
        "Pictures/Trips/2003/03-06-PerlWhirlMacMania/" .
        "Day-0-Pearl-Harbor/?show=14";
      sub re_match {
        my $str = $URI;
        my ($scheme, $rest) = $str =~ /(.*?):(.*)/;
    $ir++;
      }
      sub split_it {
        my $str = $URI;
        my ($scheme, $rest) = split /:/, $str, 2;
    $is++;
      }
      sub index_substr {
        my $str = $URI;
        my $scheme = substr($str, 0, index($str, ":")-1);
        my $rest = substr($str, index($str, ":")+1);
    $ii++;
      }

    # Счетчик цикла
    $k=1000000;
    $tt = times;
    for ($i=0;$i<$k;$i++) { &re_match; }
    print "re_match = ",times - $tt," s.\n";

    $tt = times;
    for ($i=0;$i<$k;$i++) { &split_it; }
    print "split_it = ",times - $tt," s.\n";

    $tt = times;
    for ($i=0;$i<$k;$i++) {
    &index_substr;
    }
    print "index_substr = ",times - $tt," s.\n";
    -----------------------------------------------

    Попробуйте запустить и наглядно увидите что "оптимально", а что не очень :)

     
  • 1.9, tor (??), 22:57, 14/06/2009 [ответить]  
  • +/
    Если добавить use strict; то результат изменится :-)
     

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Спонсоры:
    Слёрм
    Inferno Solutions
    Hosting by Ihor
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2019 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру