Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

FAQ

Все материалы взяты с сайта www.cpan.org .

Как инсталировать CPAN Perl modules?

Наберите perl -MCPAN -e 'install Chocolate::Belgian'. По ссылке CPAN.pm documentation можно найти более подробное описание .


Как удалить установленные Perl modules?

Для этого используйте стандартные модули ExtUtils::Installed и ExtUtils::Packlist и смотрите пример ниже :


 #!/usr/local/bin/perl -w
 
 use ExtUtils::Packlist;
 use ExtUtils::Installed;
 
 $ARGV[0] or die "Usage: $0 Module::Name\n";
 
 my $mod = $ARGV[0]; 
 
 my $inst = ExtUtils::Installed->new();
 
     foreach my $item (sort($inst->files($mod))) {
              print "removing $item\n";
              unlink $item;
           }
 
 my $packfile = $inst->packlist($mod)->packlist_file();
           print "removing $packfile\n";
           unlink $packfile;
   
 

Как мне определить - какие модули уже установлены ?

  • perldoc perllocal

    Каждый устанавливаемый модуль добавляет информацию о себе в файл perllocal.pod который лежит в районе /usr/local/lib/perl5/version number/architecture/ . Информацию о системных перловых каталогах можно извлечь с помощью perl -V.

    =head2 Wed May 12 13:42:53 1999: C<Module> L<Data::Dumper>
     
     =over 4
     
     =item *
     
     C<installed into: /usr/local/lib/perl5/5.00503>
     
     =item *
     
     C<LINKTYPE: dynamic>
     
     =item *
     
     C<VERSION: 2.101>
     
     =item *
     
     C<EXE_FILES: >
     
     =back
     
  • Использование ExtUtils::Installed
    
     #!/usr/local/bin/perl
     
     use ExtUtils::Installed;
     my $instmod = ExtUtils::Installed->new();
     foreach my $module ($instmod->modules()) {
     my $version = $instmod->version($module) || "???";
            print "$module -- $version\n";
     }
     

    что выведет примерно следующее

    
     Apache::DBI -- 0.87
     Apache::DBILogConfig -- 0.01
     Apache::DBILogger -- 0.93
     AppConfig -- 1.52
     Archive::Tar -- 0.22
     BerkeleyDB -- 0.06
     CGI -- 2.74
     CPAN -- 1.59
     CPAN::WAIT -- 0.27
     Catalog -- 1.00
     Compress::Zlib -- 1.11
     Config::IniFiles -- 2.14
     Convert::BER -- 1.26
     Coy -- ???
     Crypt::Rot13 -- 0.04
     Crypt::SSLeay -- 0.16
     DBI -- 1.14
     [.....]
     

  • Как мне определить - работает ли данный модуль на моей операционной системе?

    Зайдите на http://testers.cpan.org/ - там приведен список модулей и соответственно работающих платформ для них.


    Как вручную установить модуль в private/non-standard directory?

    Выставьте переметры PREFIX и LIB перед запуском Makefile.PL. Например:

     foo@barbell$ perl Makefile.PL LIB=/home/foobar/mylib PREFIX=/home/foobar/mylib
     

    Как использовать модули , поставленные в private/non-standard directory?

    • foo@barbell$ setenv PERL5LIB /path/to/module - из командной строки
    • use lib qw(/path/to/module); прописано в хидере скрипта.
    • foo@barbell$ perl -I/path/to/module

    При этом каждый вариант добавляет /path/to/module в @INC.


    Где бы мне найти Perl scripts?


    Perl - журналы


    Perl courses/training/on-line tutorials?

    Training

    On-line Tutorials


    Что такое Perl?

    Perl - высокоуровневый язык программирования , написанный Larry Wall (и не только). В основном он унаследовал свойства языка C и в меньшей степени - sed,awk,shell. Работа с процессами,файлами, манипуляции с текстом позволяют легко работать с системными утилитами, доступом к базе данных , графическим программированием , сетью, вебом. Этот язык особенно популярен у системных админов , веб-программистов , научных работников и т.д.

    Кто поддерживает Perl? Кто разрабатывает его? Почему он бесплатен ?

    Исторически сложившиеся традиции интернета , а также индивидуальные особенности самого Larry Wall сделали перл бесплатным и открытым . Perl поддерживается его пользователями. Сore team (Perl Porters) - группа высоко альтруистичных индивидуумов :-) обьединенных целью создания бесплатного продукта . Историю развития ядра Perl можно посмотреть на http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/ и http://archive.develooper.com/perl5-porters@perl.org/ или nntp://nntp.perl.org/perl.perl5.porters или http://nntp.perl.org/group/perl.perl5.porters , faq - http://simon-cozens.org/writings/p5p-faq , или можно подписаться на рассылку по адресу perl5-porters-request@perl.org (an empty message with no subject is fine).

    В чем разница между perl4, perl5, perl6?

    perl4 - это прошлое, perl5 - настоящее, perl6 - это будущее.

    Текущая версия на 2005-й год - perl5, реализована аж в 1994. Она совместима с perl4 (1991),но имеет такие фичи , как ссылки , модули и т.д.

    Разработка Perl6 стартовала в 2002 и до сих пор в процессе. Больше можно узнать на http://dev.perl.org/perl6/ .

    Труден ли Perl в изучении?

    Нет . Если вы раньше писали программы на С , или shell , или даже бэйсике , то освоить его будет нетрудно.

    Одним из главных свойств Perl является аксиома - "любую задачу всегда можно сделать более чем одним способом".

    Поскольку Perl - язык интерпретируемый , скрипты можно тестировать без компиляции.

    Ну и конечно огромным плюсом в изучении Perl является сам факт Unix-experience.


    Perl Books

    	Programming Perl (the "Camel Book"):
     	by Larry Wall, Tom Christiansen, and Jon Orwant
     	ISBN 0-596-00027-8  [3rd edition July 2000]
     	http://www.oreilly.com/catalog/pperl3/
     	(English, translations to several languages are also available)
     

    	The Perl Cookbook (the "Ram Book"):
     	by Tom Christiansen and Nathan Torkington,
     	    with Foreword by Larry Wall
     	ISBN 0-596-00313-7 [2nd Edition August 2003]
     	http://www.oreilly.com/catalog/perlckbk2/
     

    	Learning Perl (the "Llama Book")
     	by Randal L. Schwartz and Tom Phoenix
     	ISBN 0-596-00132-0 [3rd edition July 2001]
     	http://www.oreilly.com/catalog/lperl3/
     

    	Learning Perl Objects, References, and Modules (the "Alpaca Book")
     	by Randal L. Schwartz, with Tom Phoenix (foreword by Damian Conway)
     	ISBN 0-596-00478-8 [1st edition June 2003]
     	http://www.oreilly.com/catalog/lrnperlorm/
     

    	Perl: The Programmer's Companion
     	by Nigel Chapman
     	ISBN 0-471-97563-X [1997, 3rd printing Spring 1998]
     	http://www.wiley.com/compbooks/catalog/97563-X.htm
     	http://www.wiley.com/compbooks/chapman/perl/perltpc.html (errata etc)
     
    References
    	Programming Perl
     	by Larry Wall, Tom Christiansen, and Jon Orwant
     	ISBN 0-596-00027-8 [3rd edition July 2000]
     	http://www.oreilly.com/catalog/pperl3/
     
     	Perl 5 Pocket Reference
     	by Johan Vromans
     	ISBN 0-596-00032-4 [3rd edition May 2000]
     	http://www.oreilly.com/catalog/perlpr3/
     
     	Perl in a Nutshell
     	by Ellen Siever, Stephan Spainhour, and Nathan Patwardhan
     	ISBN 1-56592-286-7 [1st edition December 1998]
     	http://www.oreilly.com/catalog/perlnut/
     
    Tutorials
    	Beginning Perl
     	by James Lee
     	ISBN 1-59059-391-X [2nd edition August 2004]
     	http://apress.com/book/bookDisplay.html?bID=344
     
     	Elements of Programming with Perl
     	by Andrew L. Johnson
     	ISBN 1-884777-80-5 [1st edition October 1999]
     	http://www.manning.com/Johnson/
     
     	Learning Perl
     	by Randal L. Schwartz and Tom Phoenix
     	ISBN 0-596-00132-0 [3rd edition July 2001]
     	http://www.oreilly.com/catalog/lperl3/
     
     	Learning Perl Objects, References, and Modules
     	by Randal L. Schwartz, with Tom Phoenix (foreword by Damian Conway)
     	ISBN 0-596-00478-8 [1st edition June 2003]
     	http://www.oreilly.com/catalog/lrnperlorm/
     
     	Learning Perl on Win32 Systems
     	by Randal L. Schwartz, Erik Olson, and Tom Christiansen,
     	    with foreword by Larry Wall
     	ISBN 1-56592-324-3 [1st edition August 1997]
     	http://www.oreilly.com/catalog/lperlwin/
     
     	Perl: The Programmer's Companion
     	by Nigel Chapman
     	ISBN 0-471-97563-X [1997, 3rd printing Spring 1998]
     	http://www.wiley.com/compbooks/catalog/97563-X.htm
     	http://www.wiley.com/compbooks/chapman/perl/perltpc.html (errata etc)
     
     	Cross-Platform Perl
     	by Eric Foster-Johnson
     	ISBN 1-55851-483-X [2nd edition September 2000]
     	http://www.pconline.com/~erc/perlbook.htm
     
     	MacPerl: Power and Ease
     	by Vicki Brown and Chris Nandor,
     	    with foreword by Matthias Neeracher
     	ISBN 1-881957-32-2 [1st edition May 1998]
     	http://www.macperl.com/ptf_book/
     
    Task-Oriented
    	Writing Perl Modules for CPAN
     	by Sam Tregar
     	ISBN 1-59059-018-X [1st edition Aug 2002]
     	http://apress.com/book/bookDisplay.html?bID=14
     
     	The Perl Cookbook
     	by Tom Christiansen and Nathan Torkington
     	    with foreword by Larry Wall
     	ISBN 1-56592-243-3 [1st edition August 1998]
     	http://www.oreilly.com/catalog/cookbook/
     
     	Effective Perl Programming
     	by Joseph Hall
     	ISBN 0-201-41975-0 [1st edition 1998]
     	http://www.awl.com/
     
     	Real World SQL Server Administration with Perl
     	by Linchi Shea
     	ISBN 1-59059-097-X [1st edition July 2003]
     	http://apress.com/book/bookDisplay.html?bID=171
     
    Special Topics
    	Perl 6 Now: The Core Ideas Illustrated with Perl 5
     	by Scott Walters
     	ISBN 1-59059-395-2 [1st edition December 2004
     	http://apress.com/book/bookDisplay.html?bID=355
     
     	Mastering Regular Expressions
     	by Jeffrey E. F. Friedl
     	ISBN 0-596-00289-0 [2nd edition July 2002]
     	http://www.oreilly.com/catalog/regex2/
     
     	Network Programming with Perl
     	by Lincoln Stein
     	ISBN 0-201-61571-1 [1st edition 2001]
     	http://www.awlonline.com/
     
     	Object Oriented Perl
     	Damian Conway
     	    with foreword by Randal L. Schwartz
     	ISBN 1-884777-79-1 [1st edition August 1999]
     	http://www.manning.com/Conway/
     
     	Data Munging with Perl
     	Dave Cross
     	ISBN 1-930110-00-6 [1st edition 2001]
     	http://www.manning.com/cross
     
     	Mastering Perl/Tk
     	by Steve Lidie and Nancy Walsh
     	ISBN 1-56592-716-8 [1st edition January 2002]
     	http://www.oreilly.com/catalog/mastperltk/
     
     	Extending and Embedding Perl
     	by Tim Jenness and Simon Cozens
     	ISBN 1-930110-82-0 [1st edition August 2002]
     	http://www.manning.com/jenness
     
     	Perl Debugger Pocket Reference
     	by Richard Foley
     	ISBN 0-596-00503-2 [1st edition January 2004]
     	http://www.oreilly.com/catalog/perldebugpr/
     

    Perl из командной строки ?

    Запуск интерпретатора из командной строки :

        perl -de 42
     

    В таком стиле можно например использовать опции интерактивного дебага .

    Установленные модули на системе ?

    Используйте ExtUtils::Installed модуль .

    	use ExtUtils::Installed;
     
     	my $inst    = ExtUtils::Installed->new();
     	my @modules = $inst->modules();
     

    Если нужно вывести имена всех модулей - используйте File::Find::Rule:

    	use File::Find::Rule;
     
     	my @files = File::Find::Rule->file()->name( '*.pm' )->in( @INC );
     

    Или так :

        use File::Find;
         my @files;
     
         find sub { push @files, $File::Find::name if -f _ && /\.pm$/ },
              @INC;
     
     	print join "\n", @files;
     

    Проверка наличия конкретного модуля :

    	prompt% perldoc Module::Name
     

    debug Perl programs?

    Пробовали use warnings или -w?

    Или use strict? Эта директива отбивает охоту от использования неправильных ссылок , приучает к использованию префикса my, our, use vars.

    Как проверить возвращаемые значения при system call?

      open(FH, "> /etc/cantwrite")
         or die "Couldn't write to /etc/cantwrite: $!\n";
     

    profile Perl programs ?

    Используйте модуль Benchmark.pm.

      use Benchmark;
     
       @junk = `cat /etc/motd`;
       $count = 10_000;
     
       timethese($count, {
                 'map' => sub { my @a = @junk;
     			   map { s/a/b/ } @a;
     			   return @a },
                 'for' => sub { my @a = @junk;
     			   for (@a) { s/a/b/ };
     			   return @a },
                });
     

    Будет распечатано :

      Benchmark: timing 10000 iterations of for, map...
              for:  4 secs ( 3.97 usr  0.01 sys =  3.98 cpu)
              map:  6 secs ( 4.97 usr  0.00 sys =  4.97 cpu)
     

    Написание бенч-марков , вообще говоря , довольно неблагодарное занятие .

    Как ускорить программу на Perl ?

    Начинайте с алгоритма . Советы по этому поводу можно найти в книге Jon Bentley's Programming Pearls . Использование benchmarking и profile также может выявить узкие места в программе .

    Другой подход - использование autoload Perl code. Смотрите модули AutoSplit и AutoLoader . Третий подход - использование С-кода (например , модуль PDL в CPAN).

    Как сделать , чтобы Perl-программа не потребляла много памяти ?

    Если сравнить затраты на память для переменных , массивов в перл и в С , то вывод не в пользу первого .

    Но можно кое-что придумать . Например , массив из 1000 переменных типа bool занимает 20 килобайт , но его можно трансформировать в 125-байтный вектор. Модуль Tie::SubstrHash может помочь для определенных типов структур .

    • Рассмотрим пример

      	#
       	# Правильный подход
       	#
       	while (<FILE>) {
       	   # ...
       	}
       

      вместо:

      	#
       	# неправильный подход
       	#
       	@data = <FILE>;
       	foreach (@data) {
       	    # ...
       	}
       
    • Grep

      Для больших файлов вместо :

              @wanted = grep {/pattern/} <FILE>;
       

      делайте так :

              while (<FILE>) {
                       push(@wanted, $_) if /pattern/;
               }
       
    • Пример квотирования

      Избегайте избыточного квотирования - вместо :

              my $copy = "$large_string";
       

      которое сделает 2 копии $large_string , делайте так :

              my $copy = $large_string;
       

      Для больших массивов более эффективно :

              {
                       local $, = "\n";
                       print @big_array;
               }
       

      чем

              print join "\n", @big_array;
       

      или

              {
                       local $" = "\n";
                       print "@big_array";
               }
       

    • Параметры по ссылке

      Массивы и хэши нужно передавать по ссылке , а не по значению .

      Корректно ли возвращать ссылку на локальную переменную ?

          sub makeone {
       	my @a = ( 1 .. 10 );
       	return \@a;
           }
       
           for ( 1 .. 10 ) {
               push @many, makeone();
           }
       
           print $many[4][5], "\n";
       
           print "@many\n";
       

      Могу ли я откомпилировать Perl программу ?

      Вообще говоря , нет .

      Хотя есть решения - например (http://www.activestate.com/Products/Perl_Dev_Kit/) от ActiveState компилит байт-код , в частности по винду .

      Perl2Exe (http://www.indigostar.com/perl2exe.htm) - тоже под винду .

      Perl и командная строка ?

          # sum first and last fields
           perl -lane 'print $F[0] + $F[-1]' *
       
           # identify text files
           perl -le 'for(@ARGV) {print if -f && -T _}' *
       
           # remove (most) comments from C program
           perl -0777 -pe 's{/\*.*?\*/}{}gs' foo.c
       
           # make file a month younger than today, defeating reaper daemons
           perl -e '$X=24*60*60; utime(time(),time() + 30 * $X,@ARGV)' *
       
           # find first unused uid
           perl -le '$i++ while getpwuid($i); print $i'
       
           # display reasonable manpath
           echo $PATH | perl -nl -072 -e '
       	s![^/+]*$!man!&&-d&&!$s{$_}++&&push@m,$_;END{print"@m"}'
       

      CGI / Web programming на Perl?

      	http://www.perl.org/CGI_MetaFAQ.html
       

      Data: Numbers

      Почему я получаю 19.9499999999999 вместо 19.95?

      	printf "%.2f", 10/3;
       
       	my $number = sprintf "%.2f", 10/3;
       

      8-ричная система счисления ?

      Perl понимает 8-ричную и 16-ную системы счисления . В первом случае число должно начинаться с "0" , во втором с "0x". Для конвертации в 10-ную систему можно использовать oct() и hex() . Для конвертации из 10 в 8 можно использовать "%o" или "%O" sprintf() форматы.

      Типичная ошибка :

          chmod(644,  $file);	# WRONG
           chmod(0644, $file);	# right
       

      Функции round() , ceil() , floor() , Trig ?

      Для округления нужно использовать sprintf() или printf() .

          printf("%.3f", 3.1415926535);	# prints 3.142
       

      Модуль POSIX имплементирует ceil(), floor(), и ряд других функций.

          use POSIX;
           $ceil   = ceil(3.5);			# 4
           $floor  = floor(3.5);			# 3
       

      Пример :

          for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}
       
           0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7
           0.8 0.8 0.9 0.9 1.0 1.0
       

      Операции с массивами целых чисел ?

      Вызов функции для каждого элемента в массиве :

          @results = map { my_func($_) } @array;
       

      Например:

          @triple = map { 3 * $_ } @single;
       

      То же самое , но игнорировать результат :

          foreach $iterator (@array) {
               some_func($iterator);
           }
       

      Вызов для диапазона чисел :

          @results = map { some_func($_) } (5 .. 25);
       

      Или так :

          for my $i (5 .. 500_005) {
               push(@results, some_func($i));
           }
       

      will not create a list of 500,000 integers.

      Случайные числа между X и Y?

          my $number = 10 + int rand( 15-10+1 );
       

      Пример : random_int_in(50,120).

         sub random_int_in ($$) {
            my($min, $max) = @_;
             # Assumes that the two arguments are integers themselves!
            return $min if $min == $max;
            ($min, $max) = ($max, $min)  if  $min > $max;
            return $min + int rand(1 + $max - $min);
          }
       

      Data: Dates

      День недели или года ?

          $day_of_year = (localtime)[7];
       

      Модуль POSIX :

      	use POSIX qw/strftime/;
       	my $day_of_year  = strftime "%j", localtime;
       	my $week_of_year = strftime "%W", localtime;
       

      Модуль Time::Local :

      	use POSIX qw/strftime/;
       	use Time::Local;
       	my $week_of_year = strftime "%W",
       		localtime( timelocal( 0, 0, 0, 18, 11, 1987 ) );
       

      Модуль Date::Calc :

      	use Date::Calc;
       	my $day_of_year  = Day_of_Year(  1987, 12, 18 );
       	my $week_of_year = Week_of_Year( 1987, 12, 18 );
       

      Вчерашняя дата ?

      	use DateTime;
       
       	my $yesterday = DateTime->now->subtract( days => 1 );
       
       	print "Yesterday was $yesterday\n";
       

      Модуль Date::Calc :

      	use Date::Calc qw( Today_and_Now Add_Delta_DHMS );
       
       	my @date_time = Add_Delta_DHMS( Today_and_Now(), -1, 0, 0, 0 );
       
       	print "@date\n";
       

      Data: Strings

      Удалить обратный слэш ?

          s/\\(.)/$1/g;
       

      Удалить дубликаты ?

          s/(.)\1/$1/g;
       
      	my $str = 'Haarlem';   # in the Netherlands
           $str =~ tr///cs;       # Now Harlem, like in New York
       

      matching/nesting ?

      Работающий пример :

          # $_ есть строка для парсинга
       
           @( = ('(','');
           @) = (')','');
           ($re=$_)=~s/((BEGIN)|(END)|.)/$)[!$3]\Q$1\E$([!$2]/gs;
           @$ = (eval{/$re/},$@!~/unmatched/i);
           print join("\n",@$[0..$#$]) if( $$[-1] );
       

      Реверс строки ?

          $reversed = reverse $string;
       

      Табуляция ?

          1 while $string =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
       

      Модуль Text::Tabs :

          use Text::Tabs;
           @expanded_lines = expand(@lines_with_tabs);
       

      Изменить N символов в строке ?

      Доступ к началу строки - substr().

      	$string = "Just another Perl Hacker";
           $first_char = substr( $string, 0, 1 );  #  'J'
       

      Для изменения произвольного куска строки эту функцию нужно использовать с 4 параметрами :

          substr( $string, 13, 4, "Perl 5.8.0" );
       

      Или :

          substr( $string, 13, 4 ) =  "Perl 5.8.0";
       

      Изменить один символ ?

      Например , нужно поменять "whoever" или "whomever" в "whosoever" или "whomsoever". $_ - изменяемая строка :

          $count = 0;
           s{((whom?)ever)}{
       	++$count == 5   	# is it the 5th?
       	    ? "${2}soever"	# yes, swap
       	    : $1		# renege and leave it there
           }ige;
       

      В цикле :

          $WANT = 3;
           $count = 0;
           $_ = "One fish two fish red fish blue fish";
           while (/(\w+)\s+fish\b/gi) {
               if (++$count == $WANT) {
                   print "The third fish is a $1 one.\n";
               }
           }
       

      Будет напечатано : "The third fish is a red one."

      Подсчитать количество одного символа в строке ?

      Например символ (X) с использованием tr///:

          $string = "ThisXlineXhasXsomeXx'sXinXit";
           $count = ($string =~ tr/X//);
           print "There are $count X characters in the string";
       

      Теперь другая задача - число отрицательных чисел :

          $string = "-9 55 48 -2 23 -76 4 14 -44";
           while ($string =~ /-\d+/g) { $count++ }
           print "There are $count negative numbers in the string";
       

      Или :

      	$count = () = $string =~ /-\d+/g;
       

      Регистр ?

      Первый символ каждого слова заглавным :

              $line =~ s/\b(\w)/\U$1/g;
       

      "don't do it" -> "Don'T Do It". Или :

          $string =~ s/ (
                        (^\w)    #at the beginning of the line
                          |      # or
                        (\s\w)   #preceded by whitespace
                          )
                       /\U$1/xg;
           $string =~ /([\w']+)/\u\L$1/g;
       

      Все символы заглавные :

              $line = uc($line);
       

      Первый символ слова заглавный , остальные - прописные :

              $line =~ s/(\w+)/\u\L$1/g;
       

      split ?

      Имеется строка слов - удалить из нее запятые :

      SAR001,"","Cimetrix,Inc","Bob Smith","CAM",N,8,1,0,7,"Error,Core Dumped"
       

      Решение :

           @new = ();
            push(@new, $+) while $text =~ m{
         "([^\"\\]*(?:\\.[^\"\\]*)*)",?  # groups the phrase inside the quotes
              | ([^,]+),?
              | ,
            }gx;
            push(@new, undef) if substr($text,-1,1) eq ',';
       

      Добавить пробел в начало и конец строки ?

      В 2 приема :

      	s/^\s+//;
       	s/\s+$//;
       

      В 1 прием :

      	s/^\s+|\s+$//g;
       

      Для мульти-строчных строк :

          $string =~ s/^\s+|\s+$//gm;
       

      Или так :

      	$string =~ s/^[\t\f ]+|[\t\f ]+$//mg;
       

      Шаблоны из повторов символов ?

          # Left padding a string with blanks (no truncation):
       	$padded = sprintf("%${pad_len}s", $text);
       	$padded = sprintf("%*s", $pad_len, $text);  # same thing
       
           # Right padding a string with blanks (no truncation):
       	$padded = sprintf("%-${pad_len}s", $text);
       	$padded = sprintf("%-*s", $pad_len, $text); # same thing
       
           # Left padding a number with 0 (no truncation):
       	$padded = sprintf("%0${pad_len}d", $num);
       	$padded = sprintf("%0*d", $pad_len, $num); # same thing
       
           # Right padding a string with blanks using pack (will truncate):
           $padded = pack("A$pad_len",$text);
       
          $padded = $pad_char x ( $pad_len - length( $text ) ) . $text;
           $padded = $text . $pad_char x ( $pad_len - length( $text ) );
       
          substr( $text, 0, 0 ) = $pad_char x ( $pad_len - length( $text ) );
           $text .= $pad_char x ( $pad_len - length( $text ) );
       

      Выделение подстрок в строке ?

          # determine the unpack format needed to split Linux ps output
           # arguments are cut columns
           my $fmt = cut2fmt(8, 14, 20, 26, 30, 34, 41, 47, 59, 63, 67, 72);
       
           sub cut2fmt {
       	my(@positions) = @_;
       	my $template  = '';
       	my $lastpos   = 1;
       	for my $place (@positions) {
       	    $template .= "A" . ($place - $lastpos) . " ";
       	    $lastpos   = $place;
       	}
       	$template .= "A*";
       	return $template;
           }
       

      Встроенная переменная в строке ?

      Есть строка :

          $text = 'this has a $foo in it and a $bar';
       
          eval { $text =~ s/(\$\w+)/$1/eeg };
           die if $@;
       

      Или так :

          %user_defs = (
       	foo  => 23,
       	bar  => 19,
           );
           $text =~ s/\$(\w+)/$user_defs{$1}/g;
       

      Неверный префикс "$vars"?

          print "$var";   	# BAD
           $new = "$old";   	# BAD
           somefunc("$var");	# BAD
       

      Правильно :

          print $var;
           $new = $old;
           somefunc($var);
       

      Неверно :

          func(\@array);
           sub func {
       	my $aref = shift;
       	my $oref = "$aref";  # WRONG
           }
       

      Пример :

          @lines = `command`;
           print "@lines";		# WRONG - extra blanks
           print @lines;		# right
       

      Data: Arrays

      Разница между списком и массивом ?

      Массив - array - имеет переменную длину . Список - list - нет .

      Удалить duplicate elements из массива ?

      (contributed by brian d foy)

      Используйте hash.

         my %hash   = map { $_, 1 } @array;
          # or a hash slice: @hash{ @array } = ();
          # or a foreach: $hash{$_} = 1 foreach ( @array );
       
          my @unique = keys %hash;
       
      	my @unique = ();
       	my %seen   = ();
       
       	foreach my $elem ( @array )
       		{
       		next if $seen{ $elem }++;
       		push @unique, $elem;
       		}
       

      Используя grep :

         my %seen = ();
          my @unique = grep { ! $seen{ $_ }++ } @array;
       

      Найти элемент в масстве ?

      С помощью хэша :

          @blues = qw/azure cerulean teal turquoise lapis-lazuli/;
           %is_blue = ();
           for (@blues) { $is_blue{$_} = 1 }
       

      Теперь можно проверить наличие $is_blue{$some_color}.

      Для массива целых чисел :

          @primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
           @is_tiny_prime = ();
           for (@primes) { $is_tiny_prime[$_] = 1 }
           # or simply  @istiny_prime[@primes] = (1) x @primes;
       

      Теперь проверяем $is_tiny_prime[$some_number].

      Для чисел в диапазоне :

          @articles = ( 1..10, 150..2000, 2017 );
           undef $read;
           for (@articles) { vec($read,$_,1) = 1 }
       

      Теперь проверяем vec($read,$n,1) для $n.

          ($is_there) = grep /$whatever/, @array;
       

      Или так :

          $is_there = 0;
           foreach $elt (@array) {
       	if ($elt eq $elt_to_find) {
       	    $is_there = 1;
       	    last;
       	}
           }
           if ($is_there) { ... }
       

      Разница между 2-мя массивами или их пересечение ?

      И опять hash.

          @union = @intersection = @difference = ();
           %count = ();
           foreach $element (@array1, @array2) { $count{$element}++ }
           foreach $element (keys %count) {
       	push @union, $element;
       push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
           }
       

      Равны ли 2 массива ?

          $are_equal = compare_arrays(\@frogs, \@toads);
       
           sub compare_arrays {
       	my ($first, $second) = @_;
       	no warnings;  # silence spurious -w undef complaints
       	return 0 unless @$first == @$second;
       	for (my $i = 0; $i < @$first; $i++) {
       	    return 0 if $first->[$i] ne $second->[$i];
       	}
       	return 1;
           }
       

      Для сложных структур используйте модуль CPAN FreezeThaw :

          use FreezeThaw qw(cmpStr);
           @a = @b = ( "this", "that", [ "more", "stuff" ] );
       
           printf "a and b contain %s arrays\n",
               cmpStr(\@a, \@b) == 0
       	    ? "the same"
       	    : "different";
       

      Для хэша :

          use FreezeThaw qw(cmpStr cmpStrHard);
       
           %a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] );
           $a{EXTRA} = \%b;
           $b{EXTRA} = \%a;
       
           printf "a and b contain %s hashes\n",
       	cmpStr(\%a, \%b) == 0 ? "the same" : "different";
       
           printf "a and b contain %s hashes\n",
       	cmpStrHard(\%a, \%b) == 0 ? "the same" : "different";
       

      Найти первый элемент массива , для которого выполняется условие ?

      Находится первый элемент "Perl" :

      	use List::Util qw(first);
       
       	my $element = first { /Perl/ } @array;
       

      Аналогично можно использовать List::Util:

      	my $found;
       	foreach ( @array )
       		{
       		if( /Perl/ ) { $found = $_; last }
       		}
       

      С помощью индекса :

      	my( $found, $index ) = ( undef, -1 );
       	for( $i = 0; $i < @array; $i++ )
       		{
       		if( $array[$i] =~ /Perl/ )
       			{
       			$found = $array[$i];
       			$index = $i;
       			last;
       			}
       		}
       

      linked lists?

      Вообще говоря , такие списки в перле не особо инужны , поскольку мы и сами с помощью pop , shift ,unshift можем делать с массивом все что нужно .

      Но если уж сильно надо :

          $node = {
               VALUE => 42,
               LINK  => undef,
           };
       

      Теперь пробежимся :

          print "List: ";
           for ($node = $head;  $node; $node = $node->{LINK}) {
               print $node->{VALUE}, " ";
           }
           print "\n";
       

      Добавление :

          my ($head, $tail);
           $tail = append($head, 1);       # grow a new head
           for $value ( 2 .. 10 ) {
               $tail = append($tail, $value);
           }
       
           sub append {
               my($list, $value) = @_;
               my $node = { VALUE => $value };
               if ($list) {
                   $node->{LINK} = $list->{LINK};
                   $list->{LINK} = $node;
               } else {
                   $_[0] = $node;      # replace caller's version
               }
               return $node;
           }
       

      Но опять же , это все от лукавого .

      По-элементная работа с массивом ?

      Используем for/foreach:

          for (@lines) {
       		s/foo/bar/;	# change that word
       		tr/XZ/ZX/;	# swap those letters
           }
       

      Или:

          for (@volumes = @radii) {   # @volumes has changed parts
       		$_ **= 3;
       		$_ *= (4/3) * 3.14159;  # this will be constant folded
           }
       

      или :

      	@volumes = map {$_ ** 3 * (4/3) * 3.14159} @radii;
       

      Для хэша есть функция values :

          for $orbit ( values %orbits ) {
       		($orbit **= 3) *= (4/3) * 3.14159;
           }
       

      Манипуляция массива бит ?

      Используйте pack() , unpack(), vec() .

      Например:

          $vec = '';
           foreach(@ints) { vec($vec,$_,1) = 1 }
       

      Дан вектор $vec, получаем массив @ints :

          sub bitvec_to_list {
       	my $vec = shift;
       	my @ints;
       	# Find null-byte density then select best algorithm
       	if ($vec =~ tr/\0// / length $vec > 0.95) {
       	    use integer;
       	    my $i;
       	    # This method is faster with mostly null-bytes
       	    while($vec =~ /[^\0]/g ) {
       		$i = -9 + 8 * pos $vec;
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       		push @ints, $i if vec($vec, ++$i, 1);
       	    }
       	} else {
       	    # This method is a fast general algorithm
       	    use integer;
       	    my $bits = unpack "b*", $vec;
       	    push @ints, 0 if $bits =~ s/^(\d)// && $1;
       	    push @ints, pos $bits while($bits =~ /1/g);
       	}
       	return \@ints;
           }
       

      В цикле :

      	while($vec =~ /[^\0]+/g ) {
       	   push @ints, grep vec($vec, $_, 1), $-[0] * 8 .. $+[0] * 8;
       	}
       

      Используя модуль CPAN Bit::Vector:

          $vector = Bit::Vector->new($num_of_bits);
           $vector->Index_List_Store(@ints);
           @ints = $vector->Index_List_Read();
       

      Примеры с использованием vec():

          # vec demo
           $vector = "\xff\x0f\xef\xfe";
           print "Ilya's string \\xff\\x0f\\xef\\xfe represents the number ",
       	unpack("N", $vector), "\n";
           $is_set = vec($vector, 23, 1);
           print "Its 23rd bit is ", $is_set ? "set" : "clear", ".\n";
           pvec($vector);
       
           set_vec(1,1,1);
           set_vec(3,1,1);
           set_vec(23,1,1);
       
           set_vec(3,1,3);
           set_vec(3,2,3);
           set_vec(3,4,3);
           set_vec(3,4,7);
           set_vec(3,8,3);
           set_vec(3,8,7);
       
           set_vec(0,32,17);
           set_vec(1,32,17);
       
           sub set_vec {
       	my ($offset, $width, $value) = @_;
       	my $vector = '';
       	vec($vector, $offset, $width) = $value;
       	print "offset=$offset width=$width value=$value\n";
       	pvec($vector);
           }
       
           sub pvec {
       	my $vector = shift;
       	my $bits = unpack("b*", $vector);
       	my $i = 0;
       	my $BASE = 8;
       
       	print "vector length in bytes: ", length($vector), "\n";
       	@bytes = unpack("A8" x length($vector), $bits);
       	print "bits are: @bytes\n\n";
           }
       

      Data: Hashes (Associative Arrays)

      Работа с hash?

      Используем each() :

          while ( ($key, $value) = each %hash) {
       	print "$key = $value\n";
           }
       

      Для сортировки подходит foreach().

      Как найти элемент хэша по значению ?

      Создаем reverse hash:

          %by_value = reverse %by_key;
           $key = $by_value{$value};
       

      Более эффективно :

          while (($key, $value) = each %by_key) {
       	$by_value{$value} = $key;
           }
       

      Подсчитать размер хэша?

      Используем keys() :

          $num_keys = keys %hash;
       

      Отсортировать хэш по значению ?

          @keys = sort keys %hash;	# sorted by key
           @keys = sort {
       		    $hash{$a} cmp $hash{$b}
       	    } keys %hash; 	# and by value
       

      Или так :

          @keys = sort {
       		$hash{$b} <=> $hash{$a}
       			  ||
       		length($b) <=> length($a)
       			  ||
       		      $a cmp $b
           } keys %hash;
       

      Разница между "delete" и "undef" ?

      Если ключ $key присутствует в %hash, exists($hash{$key}) вернет true. Значение для этого ключа может быть undef, в этом случае $hash{$key} будет undef хотя exists $hash{$key} вернет true.

      Пример %hash :

      	  keys  values
       	+------+------+
       	|  a   |  3   |
       	|  x   |  7   |
       	|  d   |  0   |
       	|  e   |  2   |
       	+------+------+
       

      Далее

      	$hash{'a'}                       is true
       	$hash{'d'}                       is false
       	defined $hash{'d'}               is true
       	defined $hash{'a'}               is true
       	exists $hash{'a'}                is true (Perl5 only)
       	grep ($_ eq 'a', keys %hash)     is true
       

      Поэтому

      	undef $hash{'a'}
       

      теперь:

      	  keys  values
       	+------+------+
       	|  a   | undef|
       	|  x   |  7   |
       	|  d   |  0   |
       	|  e   |  2   |
       	+------+------+
       

      и далее :

      	$hash{'a'}                       is FALSE
       	$hash{'d'}                       is false
       	defined $hash{'d'}               is true
       	defined $hash{'a'}               is FALSE
       	exists $hash{'a'}                is true (Perl5 only)
       	grep ($_ eq 'a', keys %hash)     is true
       

      Теперь :

      	delete $hash{'a'}
       

      тогда :

      	  keys  values
       	+------+------+
       	|  x   |  7   |
       	|  d   |  0   |
       	|  e   |  2   |
       	+------+------+
       

      и далее :

      	$hash{'a'}                       is false
       	$hash{'d'}                       is false
       	defined $hash{'d'}               is true
       	defined $hash{'a'}               is false
       	exists $hash{'a'}                is FALSE (Perl5 only)
       	grep ($_ eq 'a', keys %hash)     is FALSE
       

      Уникальные ключи из 2-х хэшей ?

      Сначала извлекаем ключи из хэшей , затем удаляем дубликаты :

          %seen = ();
           for $element (keys(%foo), keys(%bar)) {
       	$seen{$element}++;
           }
           @uniq = keys %seen;
       

      Или :

          @uniq = keys %{{%foo,%bar}};
       

      Или :

          %seen = ();
           while (defined ($key = each %foo)) {
               $seen{$key}++;
           }
           while (defined ($key = each %bar)) {
               $seen{$key}++;
           }
           @uniq = keys %seen;
      
      Оставьте свой комментарий !

      Ваше имя:
      Комментарий:
      Оба поля являются обязательными

       Автор  Комментарий к данной статье