Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Интернет » Web-программирование » Perl: Полезные решения

Модерирует : Cheery

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6 7 8 9

Открыть новую тему     Написать ответ в эту тему

Anton_Y



Full Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
Итак.. Предлагаю создать на форуме топик где будут размещатся различные решения различных задач (типа библиотека функций).
Размещать рекомендуется с описанием (что этот код делае), с описанием переменных (желательно use strict)
p.s. размещать не обязательно свои исходники..  
мой скомный вклад.. (что сумел вспомнить:) )
 
  • исключение из массива повторяющихся записей (аналог distinct в sql) Подробнее...
  •  рекурсивный обход папок Подробнее...
  • Исключение из массива данных встречающихся в другом массиве Подробнее...
  • Perl: Перекодировка кириллического текста (win/koi/iso/utf)
  • Приведение регистра текста к нормально виду Подробнее...
  • Замена строки (выражения) в большом количестве файлов на другое Подробнее...
     
     
     
    p.s. для профи конечно это капля в море, но для новичков своеобразный faq. И предлагаю эту тему приклеить, чтобы она всегда была вверху..
    p.p.s. и постите свои фишки сюда..  

    Никаких вопросов! Только решения!

     
    Perl Cookbook on-line http://pleac.sourceforge.net/pleac_perl/index.html  
    DevShed Perl Articles http://www.devshed.com/c/a/Perl/

  • Всего записей: 582 | Зарегистр. 04-09-2002 | Отправлено: 07:12 14-07-2004 | Исправлено: Cheery, 23:38 01-03-2008
    CheRt



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Простейший Crawler:
     

    Код:
     
    #!/usr/bin/perl
    $|=1;
    use LWP;
    use LWP::UserAgent;
    my $sc_agent='Строка юзер-агента';
    my $dbf='Файл, куда линки сохраним';
     
    my $fts='pl|html|htm|php|phtml|shtml|asp|php3|php4|php5'; #типы файлов, которые остаются, после очистки мусора(картинок и т.д.)
     
    my $temp;
    my @url;
    my $base_url='http://forum.ru-board.com'; #Откуда начнем "бегать"
    unless ($base_url=~m/[\\\/][^\\\/\.]+$/) {$base_url=~s/[\\\/]$//g;}
    $url[0]=$base_url;
    my $i=0;
     
    my $linkpos;
     
    print "Crawler started[$base_url], working...\n";
     
    my $j=0;
    while ($i<5) { #$i<количество опрошенных страниц
     $linkpos=$url[$i];
     unless ($url[$i] eq '') {
        print $url[$i],"\n";
        $data=grabpage($url[$i], $sc_agent);
        $data=~s/[\r\n]+//g;
        while ($data=~m/(<a [^>]+>)/is) {
         $temp=$1; $data=~s/<a [^>]+>//is;
         $temp=~m/<a [^>]*href=['"]?([^<>'"]*)['"]?[^>]*>/is; $temp=$1;
         $temp=~s/[^a-z0-9^\.\\\/\?_\-:\+=&\%\$]+//ig;
         unless ($temp=~m/^[a-z]+:/i || $temp eq '') {
            $temp=make_full($linkpos,$temp);
             #Fixing / || \ pairs
            if ($temp=~m/^https?:\/{2}/i) {
             $temp=~s/([^:])[\\\/]{2,}/$1\//g;
            } else {
             $temp=~s/[\\\/]{2,}/\//g;
            }
             $url[$j]=$temp; #print "  - $temp\n"; Разблокировать для отладки
            $j++;
          }
        }
        @url=clear_links(@url);
        @url=clean_pairs(@url);
        select(undef,undef,undef,0.01); #Ожидание между запросами страниц, дабы не перегружать машину и канал, можно убрать
     }
     $i++;  
    }
     
    open(DF, ">$dbf");
    foreach (@url) {
     print DF "$_\n";
    }
    close(DF);
     
    sleep(10);
     
     
    sub make_full {
     my $linkpos=shift;
     my $link=shift;
     if ($link=~m/^https?:\/{2}/i) {
      return $link;
     } else {
      $linkpos=~s/\?[^\?]+$//;
      $linkpos=~s/[\/\\][^\/\\]+\.($fts)//i;
     
      $link=~s/^\.[\\\/]//g;
      $link=~s/^[\\\/][^\\\/]+[\\\/]//g;
     
      while ($link=~m/\.{2}[\\\/]/) {
       $linkpos=~s/[\\\/][^\\\/]+[\\\/]?$//;
       $link=~s/\.{2}[\\\/]//;
      }
     
      return "$linkpos/$link";
     }
    }
     
    sub clean_pairs {
     my %cleaned;
     
     foreach (@_) {
      $cleaned{$_}++;
     }
     
     my $i=0;
     @_=();
     
     foreach (keys %cleaned) {
      $_[$i]=$_;
      $i++;
     }
     
     return @_;
    }
     
    sub clear_links {
     my @url=@_;
     my (@temp,$j,$temp);
     
     $j=0;
     for (my $i=0;$i<@url;$i++) {
      $url[$i]=~m/\.([a-z0-9]+)(\?|$)/i;
      $temp=$1;
      if ($fts=~m/(^|\|)$temp(\||$)/i) {
       $temp[$j]=$url[$i]; $j++;
      }
     }
     
     return @temp;
    }
     
    sub grabpage {
     my $url=shift;
     my $uagent=shift;  
      $uagent=~s/[^a-z0-9\.\s\/\\\?\*_\+\-]+//igs;
      unless($uagent) {$uagent="NOMIA req-mod/0.1.3";}
     
     $ua=LWP::UserAgent->new;
     $ua->agent($uagent);
     
     my $req = HTTP::Request->new(GET=>$url);
     $req->content_type('text/html');
     
     my $res = $ua->request($req);
     
     if ($res->is_success) {
      return $res->content;
     } else {
      return 0;
     }
     
     undef $url; undef $req; undef $uagent;
    }
    1;
     


    ----------
    В огне бода нет и не будет!
    До встречи в СССР 2.0!

    Всего записей: 1118 | Зарегистр. 14-12-2001 | Отправлено: 18:55 02-06-2006 | Исправлено: CheRt, 18:57 02-06-2006
    baraka



    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Когда-то, где-то, нашел скрипт который хэш  
    { 'a.b.c' => 'text', ... }
     
    в
     
    { a => {
                 b => {
                          c => 'text'
                        }
              }
    }
     
    #---------------------------------------------------------------------------------------------------
    #  flat_to_nested(\%data)
    #
    #---------------------------------------------------------------------------------------------------
    sub flat_to_nested {
        my $h = shift;
        my %r;
         
        foreach my $key ( keys(%$h) ) {
            my($topKey, $lastKey, $new);
            my $value = $h->{$key};
            $topKey = $key;
     
            while ( $topKey ne "" ) {
                if ( $topKey =~ /(.*)\.(.*)/ ) {
                $topKey = $1;
                $lastKey = $2;
            } else {
                $lastKey = $topKey;
                $topKey = "";
            }
     
            if ( defined($r{$topKey}) ) {
                if ( ref $r{$topKey} eq "ARRAY" ) {
                    $r{$topKey}->[$lastKey] = $value;
                } elsif ( ref $r{$topKey} eq "HASH" ) {
                    $r{$topKey}->{$lastKey} = $value;
                }
                 
                last;
            }
             
            if ( $lastKey =~ /^\d+$/ ) {
                $new = [];
                $new->[$lastKey] = $value;
            } else {
                $new = {};
                $new->{$lastKey} = $value;
            }
     
            $r{$topKey} = $new;
            $value = $new;
     
            }
        }
        return $r{""};
    }

    Всего записей: 313 | Зарегистр. 29-01-2003 | Отправлено: 21:29 23-06-2006
    Kokoc

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Простой парсер XML-файлов
    На выходе формирует хэш, у которого ключи составляются из параметров XML, разделенными точками; текстовые строки перекодируются в CP1251 (хотя можно выбросить функцию utf2wn и использовать UTF-8)

    Код:
     
    use strict;
    use XML::Parser
     
    our @el=(); # компоненты ключей хэша
    our %doc= (); # собственно данные
     
    my $parser = new XML::Parser(Style=>'Tree');
    $parser->setHandlers(Start => \&start_handler,  End   => \&end_handler,  Char  => &char_handler);
    $parser->parsefile('test.xml');
    # Тут все закончивается. Начинаются процедуры обработки
     
    sub start_handler
    {
        my $expat = shift;
        my $element = shift;
        my $e;
        push(@el,$element);
        while (@_) {
            my $attr = shift;
            my $val = shift;
            $e=join(".",@el).'.'.$attr;
            $doc{$e} = utf2win($val);  
        }
    }
     
    sub char_handler {
        my($expat, $data) = @_;
        return if $data =~ /^\s+$/;
        my $e=join(".",@el);
        $doc{$e}.=utf2win($data);
    }
     
    # Конец обработки тэга.
    # Внутри процедуры мы получаем ассоциативный массив,
    # в котором можем анализировать $element (т.е. </element>)
    # и если закрывается то, что надо - обрабатываем %
    sub end_handler {
        my($expat, $element) = @_;
        pop @el;
        # проверяем значение элемента и обрабатываем хэш
    }    
     

    Например, пусть XML имеет вид:

    Код:
     
    <?xml version="1.0" encoding="windows-1251"?>
    <Document Number="1" Date="2006-06-27">
      <Payer Name="Иванов" Account="123" Summa="100.20"/>
      <Payee Name="Петров" Account="777" Summa="15.0"/>
      <Purpose>Тестовая строка</Purpose>
    </Document>
     

    то можно слегка изменить end_handler так:

    Код:
     
    sub end_handler {
        my($expat, $element) = @_;
        pop @el;
        # проверяем значение элемента и обрабатываем хэш
        if($element eq 'Document') {
            print 'Плательщик: '.$doc{'Payer.Name}.' Сумма: '.$doc{'Payer.Summa'}
        }
    }    
     

    Соответственно, остальные компоненты можно получить как $doc{'Payee.Account'}, $doc{'Purpose'} и проч.
    Текстовые данные на выходе всегда перекодируются парсером в UTF-8, поэтому нужно подключать функцию перекодировки utf2win (здесь ее код не приводится).
     
    Цикл тестовой печати foreach... print... можно вынести и за пределы end_handler, но лучше обрабатывать именно в нем - тогда в одном XML можно деражать несколько <Document>'ов

    Всего записей: 793 | Зарегистр. 06-06-2002 | Отправлено: 19:09 27-06-2006
    OLEX



    Silver Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Шаблоны для веб-типографики
     
    Скрипт последовательно перебирает имеющиеся шаблоны поиска, и для каждого из них пытается найти в строке все совпадения. В случае успеха совпавшая часть строки заменяется по правилу, указанному в шаблоне замены. Ниже подробно разобрана работа каждой пары шаблонов. Описания следуют в порядке увеличения сложности; этот порядок не совпадает с последовательностью шаблонов в реальном скрипте. При изменении таблицы правил следует учитывать, что исходная строка подвергается обработке в соответствии со всеми шаблонами, поэтому необходимо следить за тем, чтобы последующие правила не искажали действие предыдущих.
     
    Примечание. Далее описано большее число шаблонов, чем в примере из предыдущей статьи. Шаблоны в списке не являются истиной в последней инстанции.
     
    Для правильной работы регулярных выражений необходимо установить русскую локаль:
     

    Код:
    use POSIX;
    POSIX::setlocale (&POSIX::LC_ALL, "ru");
    use locale;

     
    Удаление лишних пробелов
    поиск:  '  +'
    замена: ' '
     
    Сопоставление с таким шаблоном поиска находит в тексте непрерывные последовательности, состоящие из двух или более пробелов. В регулярном выражении всего три символа: два пробела и плюс. Пробелы должны совпасть сами с собой, а символ + указывает на то, что предшествующий ему пробел обязан повториться один или более раз. Найденные последовательности заменяется строкой, содержащей один пробел.
     
    Замена дефиса длинным тире
    поиск:  ' - '
    замена: '&nbsp;&#151; '
     
    Последовательность символов пробел-дефис-пробел в большинстве случаев означает, что здесь должно стоять тире. Поскольку тире не должно отрываться от предшествующего текста и появляться на следующей строке, перед ним необходимо поставить неразрывный пробел. Таким образом, шаблон-замена принимает указанный вид.
     
    Тире в прямой речи
    поиск:  '^- '
    замена: '&#151; '
     
    Особо следует отметить случай замены дефиса тире, когда оно обозначает прямую речь, поэтому появляется в начале строки. Чтобы привязать положение дефиса к первой позиции, достаточно поставить перед ним символ ^. Естественно, что в шаблоне-замене неразрывный пробел уже не нужен.
     
    Открывающие кавычки
    поиск:  '\s"(\S)'
    замена: ' &#171;$1'
     
    Здесь впервые встретились особые переменные, имя которых состоит только из цифр. После сравнения с шаблоном такие переменные получают значения, соответствующие фрагментам регулярного выражения, заключенным в круглые скобки. Шаблон поиска начинается с метасимвола \s, совпадающего с пробелом, табуляцией или символом перевода строки (последнее совпадение вызвано тем, что во время подстановки шаблона включается многострочный режим из-за наличия модификаторов /gm). Далее следует символ дюйма, который будет заменен левой кавычкой-«елочкой», а после этого в скобках стоит метасимвол \S, он совпадает с любым символом, который не входит в набор символов, совпадающих с \s.
     
    Иными словами, весь шаблон совпадет, если найдется любой символ, слева от которого стоят пробел и символ дюйма. Строка замены формируется из пробела, символа левой кавычки (&#171;) и значения переменной $1, в которой окажется символ, следующий за кавычкой.
     
    Пару шаблонов для расстановки кавычек можно несколько изменить, чтобы они правильно реагировали на кавычки, появившиеся в начале строки:
     
    поиск:  '(^|\s)"(\S)'
    замена: '$1&#171;$2'
     
    В отличие от предыдущего случая, теперь символ дюйма может появиться как после пробела (или табуляции или перевода строки), так и в начале строки. Возможность выбора в регулярных выражениях обозначают вертикальной чертой. Для того, чтобы ограничить действие зоны выбора, поставлены круглые скобки. Однако новые скобки приведут и к дополнительной переменной $2 (именно в нее будет записан символ, следующий после кавычки). Поэтому следует изменить и шаблон-замену.
     
    Закрывающие кавычки
    поиск:  '(\S)"([ .,?!])'
    замена: '$1&#187;$2'
     
    Поиск открывающих и закрывающих кавычек имеет общие черты, за исключением того, что шаблоны поиска для этих случаев почти зеркально повторяют друг друга. Перед кавычкой должен быть непробельный символ, а после — пробел или знак препинания. Поэтому в регулярном выражении появился символьный класс [ .,?!]. Такая конструкция совпадает с одним (и только одним) из символом, указанных в квадратных скобках. В шаблоне замены вновь присутствуют переменные $1 и $2, а между ними помещен код правых кавычек.
     
    Как и ранее, допустимо включить в шаблон символ конца строки $, указав его как альтернативу символьному классу:
     
    поиск:  '(\S)"([ .,?!]|$)'
    замена: '$1&#187;$2'
     
    Примечание. Если оба аргумента оператора выбора | — единичные символы, то конструкции a|b и [ab] эквивалентны. В обоих случаях шаблон совпадет с каким-либо из двух указанных символов. Однако, если в списке присутствует символ конца строки, следует пользоваться только оператором |.
     
    Диапазоны численных значений
    поиск:  '(\d)-(\d)'
    замена: '$1&#150;$2'
     
    Диапазон значений обычно указывают либо с помощью тире, либо многоточием. Если между двумя цифрами (именно цифрами, а не обязательно числами) стоит дефис, скорее всего здесь записан интервал, и дефис следует изменить на среднее или длинное тире (по вкусу). Совпадение с цифрой выполняет метасимвол \d. Кстати, вместо него можно записать символьный класс [0123456789], или в сокращенной записи, [0-9].
     
    Многоточие
    поиск:  '\.{3}'
    замена: '&#133;'
     
    Для обозначения многоточия существует особый символ &#133;. Регулярное выражение ищет последовательности из трех точек. Сам символ «точка» в регулярных выражением означает совпадение с любым символом, поэтому его необходимо экранировать обратным слэшем. Квантификатор {3} указывает, что предыдущий символ должен повториться ровно три раза.
     
    Слова, написанные через дефис
    поиск:  '(\S+)-(\S+)'
    замена: '<nobr>$1-$2</nobr>'
     
    Двойные слова (например, «по-русски», «два-три») обычно лучше смотрятся, если они не разрываются на месте дефиса. Чтобы избежать переноса на новую строку, достаточно обрамить такие слова тегами <nobr>…</nobr>. В шаблоне поиска две одинаковые конструкции (\S+), которые совпадают с двумя разделенными дефисом последовательностями непробельных символов. Найденные слова попадают в переменные $1 и $2.
     
    Неразрывный пробел после инициалов
    поиск:  '(\w\.)\s(\w\.)\s(\w\w+)'
    замена: '$1&nbsp;$2&nbsp;$3'
     
    Инициалы можно определить, если после одиночной буквы (она совпадает с метасимволом \w) стоят точка и пробел. Приведенное выше регулярное выражение помещает в переменные \$1 и $2 инициалы (вместе с точками), а в переменную $3 — фамилию. Шаблон-заменитель соединяет найденные подстроки неразрывными пробелами.
     
    Полезно предусмотреть также шаблон, в котором указан только один инициал:
     
    поиск:&nbsp; '(\W\w\.)\s(\w\w+)'
    замена: '$1&nbsp;$2'
     
    Неразрывный пробел после цифр
    поиск:  '(\d)\s'
    замена: '$1&nbsp;'
     
    Поведение регулярных выражений аналогично расстановке пробелов после инициалов.
     
    Неразрывный пробел после коротких слов
    my $preps = "я|ты|мы|вы|не|ни|на|но|в|во|до|от|и|а|ее|".
       "он|с|со|о|об|ну|к|ко|за|их|из|ей|ой|ай";
     
    поиск:  "(\\s|^)((?:$preps)[.,]?)\\s",
    замена: '$1$2&nbsp;'
     
    Слова, состоящие из одной или двух букв, обычно желательно переносить на новую строку вместе с последующими словами. (Кроме случая, когда такое слово стоит в конце строки: здесь лучше переносить на новую строку два последних слова.) Следует различать предлоги, местоимения и некоторые другие слова от частиц типа «ли» (последние желательно оставлять на одной строке с предшествующим словом или переносить их оба). Список коротких слов записан в переменной $preps через символ выбора. Отдельная переменная сделана не случайно — далее ее можно повторно применять в других регулярных выражениях. Кроме того, они становятся проще и логичнее.
     
    Обратите внимание, шаблон замены заключен в двойные кавычки, поэтому Perl подставляет в него значение переменной $preps. По этой же причине теперь следует экранировать символ обратного слеша.
     
    Рассмотрим шаблон подробнее. Вначале стоит знакомая конструкция (\s|^), совпадающая с пробелом или началом строки. В конце шаблона указан метасимвол \s, который потребует пробел в исходной строке.
     
    Осталось разобрать подшаблон ((?:$preps)[.,]?). Во-первых, на место переменной $preps подставляется строка альтернатив, определенная ранее. После нее указан символьный класс [.,], совпадающий либо с точкой, либо с запятой. Наличие одного из этих символов не обязательно: об этом говорит квантификатор ?. Если символьный класс поместить непосредственно после переменной, Perl станет интерпретировать последовательность $preps[.,] как элемент массива @preps с индексом [.,], что вызовет ошибку на этапе компиляции программы. Поэтому следует отделить левую квадратную скобку от имени переменной. Это можно сделать так: ($preps)[.,]. Теперь ошибка не возникнет, но появится дополнительная переменная $n. Чтобы скобки выполняли только функцию группировки, указан модификатор ?:, в этом случае совпавшее внутри круглых скобок выражение не будет копироваться в отдельную переменную.
     
    Наконец, можно выполнять замену. Значимые части выражения содержатся в переменных $1 и $2, а после них следует поставить неразрывный пробел &nbsp;.
     
    Пробелы около двух коротких слов
    поиск:  "(\\s|^)((?:$preps)[., ]\\s?(?:$preps)[.,]?)\\s(\\S+)",
    замена: '$1<nobr>$2 $3<\/nobr>',
     
    Если подряд идут два коротких слова, ранее описанный шаблон распознает только одно из них. Чтобы обработать последовательности из двух коротких слов и следующего за ними слова, в шаблон для поиска следует вставить еще одну конструкцию ((?:$preps)[., ]), за которой возможно последуют пробелы. В конце всего выражения делается попытка отыскать следующее слово.
     
    Неразрывный пробел перед короткими частицами
    my $posts = "ли|ль|же|ж|бы|б";
     
    поиск:"(\\S+)\\s($posts(?:[ .,!?]))",
    замена: '$1&nbsp;$2'
     
    Это правило размещает неразрывный пробел непосредственно перед любым из вариантов слов, перечисленных в переменной $posts. В остальном работа шаблонов аналогична происходящему в двух предыдущих случаях.
     
    © http://regexp.ru

    Всего записей: 3591 | Зарегистр. 09-07-2002 | Отправлено: 11:23 19-07-2006
    Kokoc

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    О разборке текстовых файлов в кодировке DOS в Active Perl (Windows)
     
    Чтобы использовать кодировку CP866 в регулярных выражениях, функциях lc(), uc() и пр., добавьте в начало файла:
     

    Код:
     
    use locale;
    use POSIX qw(locale_h);
    setlocale(LC_ALL,"Russian_Russia.866");
     

     
    Для KOI-8:

    Код:
     
    use locale;
    use POSIX qw(locale_h);
    setlocale(LC_ALL,"Russian_Russia.2086");
     

     
     
    Для windows-1251, то используйте

    Код:
     
    use locale;
    use POSIX qw(locale_h);
    setlocale(LC_ALL,"Russian_Russia.1251");
     

    (или вообще не включать setlocale() - бует использоваться системная локаль).
     
    (обратите внимание, что в windows имена отличаются от unix (ru_RU.nnn))

    Всего записей: 793 | Зарегистр. 06-06-2002 | Отправлено: 21:42 23-07-2006
    antyan



    Newbie
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Определение айпи пользователя:
     

    Цитата:
     
    function getIP()
    {
        if (getenv("HTTP_CLIENT_IP")) $ip = getenv("HTTP_CLIENT_IP");
        else if(getenv("HTTP_X_FORWARDED_FOR")) $ip = getenv("HTTP_X_FORWARDED_FOR");
        else if(getenv("REMOTE_ADDR")) $ip = getenv("REMOTE_ADDR");
        else $ip = "UNKNOWN";
        return $ip;
    }
     
    $ip = getIP();
     


    Всего записей: 24 | Зарегистр. 08-09-2006 | Отправлено: 08:20 08-09-2006
    CheRt



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Так будет немного "перловее"

    Код:
     
    sub getIP()  
    {  
        if ($ENV{'HTTP_CLIENT_IP'}) $ip=$ENV{'HTTP_CLIENT_IP'};  
        elsif($ENV{'HTTP_X_FORWARDED_FOR'}) $ip=$ENV{'HTTP_X_FORWARDED_FOR'};  
        elsif($ENV{'REMOTE_ADDR'}) $ip=$ENV{'REMOTE_ADDR'};  
        else $ip = 'UNKNOWN';  
        return $ip;  
    }  
     
    $ip = getIP();
     


    ----------
    В огне бода нет и не будет!
    До встречи в СССР 2.0!

    Всего записей: 1118 | Зарегистр. 14-12-2001 | Отправлено: 14:13 08-09-2006 | Исправлено: CheRt, 20:29 03-02-2007
    Kokoc

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Или так:

    Код:
     
    $ip='UNKNOWN';
    map {   $ip=$ENV{$_} if $ENV{$_}; } (HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','REMOTE_ADDR');
     

    Всего записей: 793 | Зарегистр. 06-06-2002 | Отправлено: 16:56 08-09-2006
    alex99a

    Junior Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Или так:
     

    Цитата:
     
    sub getip {
    return($ENV{'HTTP_CLIENT_IP'} || $ENV{'HTTP_X_FORWARDED_FOR'} || $ENV{'REMOTE_ADDR'} || 'UNKNOWN');
    }
     

     

    Всего записей: 40 | Зарегистр. 27-03-2006 | Отправлено: 21:30 26-09-2006
    CheRt



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Простая, но временами полезная при дебагинге и оптимизации вещь:

    Код:
     
    #!/usr/bin/perl
     
    print "Content-type:text/plain;\n\n";
    foreach (sort keys %ENV) {
     if (length($_)>=16) {
      print "$_\t=\t$ENV{$_}\n";
     } elsif (length($_)<16 && length($_)>8) {
      print "$_\t\t=\t$ENV{$_}\n";
     } else {
      print "$_\t\t\t=\t$ENV{$_}\n";
     }
    }
     


    ----------
    В огне бода нет и не будет!
    До встречи в СССР 2.0!

    Всего записей: 1118 | Зарегистр. 14-12-2001 | Отправлено: 08:23 11-10-2006
    CheRt



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Читаем файл с конца(не слишком быстрое, но иногда нужное решение):
     

    Код:
     
    #!/usr/bin/perl
    ############
    # Использование функции:
    # @array=ioFileReadBottomLines('имя_файла', число_строк);
    ############
    $|=1;
     
    print join("\n", ioFileReadBottomLines($0, 34));
    sleep(10);
     
    sub ioFileReadBottomLines {
        my $file = shift;
        my $lines = abs(int(shift)) || 20;
        
        my $fc = 0;
        my ($string, @res);  
     
        open(my $tfh, '<', $file)
            || die("Can't tail $file: $!\n");  
        while ($lines)
        {
            sysseek($tfh, --$fc, 2);  
            sysread($tfh, my $buffer, 1);  
            if ( $buffer =~ m/[^\n]/ )
            { # Формируем строку, пока не наткнулись на перенос
                $string = $buffer.$string;  
            } else
            { # Записываем очередную строку
                $string =~ s/\r//;
                unshift(@res, $string);  
                $string = '';
                $lines--;
            }  
        }  
        close($tfh);
     
        return @res;
     

     
    Простейший метод помещения документации по perl на сайте(не полная реализация с исключениями, а лишь идея на примере функций win-perl):
     

    Код:
     
    use CGI qw/param/;
    my $funcname=param('FUNC');
    print "Content-type: text/plain;\n\n", system("perldoc -f $funcname");
     


    ----------
    В огне бода нет и не будет!
    До встречи в СССР 2.0!

    Всего записей: 1118 | Зарегистр. 14-12-2001 | Отправлено: 20:40 17-01-2007 | Исправлено: CheRt, 15:57 11-09-2012
    tolyn77



    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    CheRt
    не работает у меня пустоту пишет этот код

    Код:
     
    #!/usr/bin/perl
    $|=1;
     
    my $file='seek.txt'; #Из какого файла читаем?
    my $num=2; # Сколько строк нам надо прочитать?
    my $i=0;
    my $buffer;
    my $fc=-1;
    my $pos;
     
    open(F, $file);
     while ($num) {
      sysseek(F, $fc, 2);
      sysread(F, $data, 1);
      if ($data=~m/[^\n]/) {
        $buffer=$data.$buffer;
      } else {
        $_[$i]=$buffer;
        $buffer='';
        $i++;
        $num--;
      }
      $fc--;
     }
    close(F);
     
    print join("\n", @_);
    sleep(10);
     

    правда я пытаюсь лог апача смотреть

    Всего записей: 1499 | Зарегистр. 07-09-2004 | Отправлено: 18:39 18-01-2007
    Liksu



    Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Мне когда-то показали два варианта чтения последних допустим 27 строк:
     

    Код:
     
    #!/usr/local/bin/perl -w
    print "Content-type: text/plain\n\n";
    open(LOG,"/home/error_log");
      @all=<LOG>;
    close(LOG);
    print @all[-27..-1];
     

     
    и
     

    Код:
     
    #!/usr/local/bin/perl -w
    print "Content-type: text/plain\n\n";
    print `tail -n 27 /home/error_log`;
     


    ----------
    Хочу запустить:
    deep.exe megahit /u Liksu

    Всего записей: 289 | Зарегистр. 21-01-2002 | Отправлено: 23:50 19-01-2007
    CheRt



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Не совсем "полезное решение", тем не менее запощу, дабы тема не умирала:
     
    Perl - утечка памяти на локальных переменных.
     
    "Фича" заключается в том, что интерпритатор не убивает локальные переменные после выхода из блока, в котором они определены(для понимания остановимся на подпрограмме sub ... { ... } ), лишь изменяет содержимое с последующими вызовами. Очистка памяти возникает лишь когда не будет более ссылок на подпрограмму, либо будет вызвана функция exit.
     
    Пусть у нас есть подпрограмма, которая генерирует или получает большую структуру данных. Допустим, что вся обработка данных, выдаваемых этой подпрограммой будет произведена до следующего вызова функции. В таком случае при реализации вида my @array=funcName([params]) произойдет дублирование памяти и если мы имеем значительный размер структуры данных это приведет практически к удвоению требуемой оперативной памяти.
    Что делать? Использовать ссылки + очищать стуктуру в начале подпрограммы, если данные предыдущего вызова не нужны!
     
    Пример:

    Код:
     
    #!/usr/bin/perl
    $|=1;
     
    my $link=longArray(1024, 1024*1024);
     
    print ">> $link->[0]\n";
     
    sleep(10);
     
    sub longArray {
        my @array=(); # Инициируем локальный для блока массив и сразу очищаем его
        my ($strLen, $arrSize) = (shift, shift);
        # Заполняем массив
        while ($arrSize>=0) {
            $array[--$arrSize]=chr(int(rand(255.999))) x $strLen;
        }
        return \@array; # Возвращаем ссылку на массив, а не саму структуру
    }
     

     
    вместо  
     

    Код:
     
    #!/usr/bin/perl
    $|=1;
     
    my @arr=longArray(1024, 1024*1024);
     
    print ">> $arr[0]\n";
     
    sleep(10);
     
    sub longArray {
        my @array=();
        my ($strLen, $arrSize) = (shift, shift);
        while ($arrSize>=0) {
            $array[--$arrSize]=chr(int(rand(255.999))) x $strLen;
        }
        return @array;
    }
     


    ----------
    В огне бода нет и не будет!
    До встречи в СССР 2.0!

    Всего записей: 1118 | Зарегистр. 14-12-2001 | Отправлено: 02:04 26-04-2007
    CheRt



    Advanced Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    Удобные иногда обработки даты/времени:
     

    Код:
     
    package Date;
     
    sub Formatted {
        my $template=shift;
        my $utime=shift;
        my ($second,$minute,$hour,$day,$month,$year);
        if ($utime) {
            ($second,$minute,$hour,$day,$month,$year)=(localtime($utime))[0..5];
        } else {
            ($second,$minute,$hour,$day,$month,$year)=(localtime())[0..5];
        }
     
        $second="0$second" if $second<10;
        $minute="0$minute" if $minute<10;
        $hour="0$hour" if $hour<10;
        $day="0$day" if $day<10;
        $month++; $month="0$month" if $month<10;
     
        $year+=1900;
     
        my $unixtime=$utime || time();
     
        $template=~s/\$second/$second/i;
        $template=~s/\$minute/$minute/i;
        $template=~s/\$hour/$hour/i;
        $template=~s/\$day/$day/i;
        $template=~s/\$month/$month/i;
        $template=~s/\$year/$year/i;
        $template=~s/\$unixtime/$unixtime/i;
     
        return $template;
    }
     
    sub UTime {
        my ($year, $month, $day) = (shift, shift, shift);
        $year-=1970 if ($year>=1970);
     
        $day+=31 if ($month==2);
        $day+=59 if ($month==3);
        $day+=90 if ($month==4);
        $day+=120 if ($month==5);
        $day+=151 if ($month==6);
        $day+=181 if ($month==7);
        $day+=212 if ($month==8);
        $day+=243 if ($month==9);
        $day+=273 if ($month==10);
        $day+=304 if ($month==11);
        $day+=334 if ($month==12);
     
        $day+=int(($year+2)/4) - 1;
     
        return int(($year*365 + $day)*86400 - 10799);
    }
     
    1;
     

     
    Использование
    $string=Date::Formatted('$year/$month/$day, $hour:$minute:$second', [$unixtime]);
     
    $utime=Date::UTime($year, $month, $day);
     
    ----
    wellic, да бредовая штука в общем-то для повседневки, просто нужна была для максимально быстроработающей программы, т.е. избавлялись с ребятами от универсальных библиотек.
    Но тему то оживить стоило
    \/                \/

    ----------
    В огне бода нет и не будет!
    До встречи в СССР 2.0!

    Всего записей: 1118 | Зарегистр. 14-12-2001 | Отправлено: 12:00 21-05-2007 | Исправлено: CheRt, 20:56 22-05-2007
    wellic

    Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Прикольно, но кто хочет вообще по всякому с датами изголяться, то есть модуль Date::Manip
     

    Всего записей: 339 | Зарегистр. 06-05-2002 | Отправлено: 01:11 22-05-2007
    pushey

    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Подскажите пожалуйста как удалить из массива неповторяющиеся записи, которые встречаются один раз.




    для тех, кто в танке.. здесь не задают вопросов /Cheery/

    Всего записей: 11 | Зарегистр. 27-07-2006 | Отправлено: 14:55 24-05-2007 | Исправлено: Cheery, 18:38 24-05-2007
    yarnik



    Member
    Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
    календарик с учетом высокосного года

    Код:
    @month=qw(январь февраль март апрель май июнь июль август сентябрь октябрь ноябрь декабрь);
    @mdays = qw(31 28 31 30 31 30 31 31 30 31 30 31); if (($newyear % 4) == 0) { $mdays[1] = 29; }
    for $newmon (0..11) {
      print "$month[$newmon]";
      for (0..$mdays[$newmon]) { print "$_"; }
    }


    Всего записей: 279 | Зарегистр. 09-06-2004 | Отправлено: 17:17 07-06-2007 | Исправлено: yarnik, 17:17 07-06-2007
    Yashin



    Newbie
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Попытка создать date() как в php.
    Код:
    use strict;
    print "Content-Type: text/html\n\n";
     
    sub phpDate {
        my %temp;
        $temp{ 'shift' } = shift;
        $temp{ 'mr' } = [ 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь','Октябрь', 'Ноябрь', 'Декабрь' ];
        $temp{ 'dr' } = [ 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье' ];
        ( $temp{ 's' }, $temp{ 'm' }, $temp{ 'h24' }, $temp{ 'dn' }, $temp{ 'mn' }, $temp{ 'y' }, $temp{ 'dw' }, $temp{ 'dy' }, $temp{ 'isdst' } ) = localtime( time() );
        $temp{ 'h12' } = $temp{ 'h24' };
        $temp{ 'h12' } = ( $temp{ 'h24' } - 12 ) if ( $temp{ 'h24' } > '12' );
        $temp{ 'ap' } = 'am';
        $temp{ 'ap' } = 'pm' if ( $temp{ 'h24' } > 12 );
        $temp{ 'y' } += 1900;
        $temp{ 'mnn' } = $temp{ 'mn' } ++;
        $temp{ 'dw' } --;
        #
        if ( $temp{ 'shift' } ) {
            $temp{ 'shift' } =~ s/s/$temp{ 's' }/g;
            $temp{ 'shift' } =~ s/i/$temp{ 'm' }/g;
            $temp{ 'shift' } =~ s/g/$temp{ 'h12' }/g;
            $temp{ 'shift' } =~ s/G/$temp{ 'h24' }/g;
            $temp{ 'shift' } =~ s/a/$temp{ 'ap' }/ig;
            $temp{ 'shift' } =~ s/d/$temp{ 'dn' }/g;
            $temp{ 'shift' } =~ s/D/$temp{ 'dr' }[ $temp{ 'dw' } ]/g;
            $temp{ 'shift' } =~ s/m/$temp{ 'mnn' }/g;
            $temp{ 'shift' } =~ s/M/$temp{ 'mr' }[ $temp{ 'mn' } ]/g;
            $temp{ 'shift' } =~ s/y/$temp{ 'y' }/ig;
        } else {
            $temp{ 'shift' } = time();
        }
        return $temp{ 'shift' };
    }
    Описание переменных:
    Код:
     s - секунды
    i - минуты
    g - часы от 0 до 12
    G - часы от 0 до 24
    a(A) - am/pm (день/ночь)
    d - день от 0 до 30(31)
    D - Понедельник, Вторник ... Воскресения
    m - месяц от 1 до 12
    M - Январь, Февраль ... Ноябрь
    y(Y) - Год
    Пример:
    Код:
    phpDate( 'D M y G:i:s' );
    Результат:
    Код:
    Среда Июль 2007 23:19:11

    Если значения не задано то выводит результат time()
     
    P.S. Бить не надо, только учусь.

    Всего записей: 2 | Зарегистр. 17-06-2006 | Отправлено: 16:55 15-06-2007
    Nekt

    Advanced Member
    Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
    Ошибся.

    Всего записей: 640 | Зарегистр. 24-01-2006 | Отправлено: 17:31 04-07-2007 | Исправлено: Nekt, 17:59 04-07-2007
    Открыть новую тему     Написать ответ в эту тему

    Страницы: 1 2 3 4 5 6 7 8 9

    Компьютерный форум Ru.Board » Интернет » Web-программирование » Perl: Полезные решения


    Реклама на форуме Ru.Board.

    Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
    Modified by Ru.B0ard
    © Ru.B0ard 2000-2024

    BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

    Рейтинг.ru