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

FAQ

Оргинал лежит на http://faq.perl.org/
 Programming Tools
 
 1.  Интерактивный дебаг
 2.  Определить срисок модулей , установленных на системе
 3.  Дебаг программ
 4.  Профайлинг 
 5.  Среда 
 6.  Интеграция curses   
 7.  Как ускорить работу перла ?
 8.  Как уменьшить затраты на память ?
 9.  Можно ли возвращать из функции ссылку на локальную переменную ?
 10. Как увеличить скорость загрузки CGI-скриптов ?
 11. Как закрыть исходники ?
 12. Как откомпилировать перловый код в байт-код
 13. Литература по OOP Perl
 14. Линковка Си и Perl
 15. Как получить полный список ошибок в Перл
 16. Что такое MakeMaker
 
 Data Manipulation
 
 1.  Как задать точность до знака после запятой в типе float ?
 2.  Конвертация данных в 8- и 16-ричном формате
 3.  Округление чисел
 4.  Как оперировать с матрицами
 5.  Как передать массив в функцию и вернуть результат в этот же массив 
 6.  Как получить случайные числа в диапазоне 10-15
 7.  Работа с датами 
 8.  Как проверять валидность данных
 9.  Как удалить/заменить/посчитать повторяющиеся символы 
 10. Как работает substr
 11. Как подсчитать число вхождений подстроки в строку ?
 12. Как работает функция split ?
 13. Как удалить повторы из массива ?
 14. Как определить - есть ли в данном массиве данный элемент ?
 15. Как вычислить разницу или пересечение между двумя массивами ?
 16. Как проверить на эквивалентность 2 массива  ?
 17. Как проверить - есть ли данный элемент в массиве ?
 18. Нужны ли связные списки в перле ?
 19. Как отсортировать массив ?
 20. Пусть имеется массив . Как составить все-возможные комбинации из его элементов ?
 21. Как оперировать операциями на битами ?
 22. Как работать с хешем ?
 23. Можно ли в хеш добавлять-удалять ключ в момент итерации над этим хешем ?
 24. Как отыскать хеш по значению ?
 25. Как узнать число элементов хеша ?
 26. В чем разница между функциями delete и undef для хеша ?
 27. Как получить уникальные ключи из 2-х хешей ?
 28. Как в перле создать структуру , аналогичную си-шной по синтаксису ?
 29. Как определить тип скаляра ?
 30. Как сохранить данные между вызовами скрипта ?
 31. Как можно использовать класс UNIVERSAL ?
 
 Files
 
 1. Как изменить , удалить или добавить строку в файл ?
 2. Как подсчитать число строк в файле ?
 3. Как скопировать файл ?
 4. Как обращаться с хенлами файлов на процедурном уровне в качестве параметров ?
 5. Можно ли использовать файловый хендл косвенно ?
 6. Как открыть файл на чтение-запись ?
 7. Как переименовать файл ?
 8. Как открыть текстовой файл , прочитать оттуда число , сделать инкремент 
 9. Как изменить бинарный файл ?
 10.Как получить время изменения файла ?
 
 Regular Expressions
 
 1. В каком стиле лучше писать регеспы ?
 2. Как сделать , чтобы работала русская локаль для \w match ?
 3. Как квотировать переменную внутри регеспа ?
 4. Можно ли отдебажить регулярное выражение ?
 5. Как вырезать из файла комменты в стиле си ?
 6. Как правильно использовать т.н. квантификаторы - quantifiers (?, *, +, {}) ?
 7. Как работает  \b ?
 8: Где можно применять \G ?
 
 General Perl Language Issues 
 
 1. Каковы основные спецификаторы типов :
 2. Как проигнорировать возвращаемые значения ?
 3. Можно ли блокировать варнинги ?
 4. Что такое extension ?
 5. Как создать структуру ?
 6. Как передать - и - вернуть из функции такие обьекты , как :
 7. Как создать статическую переменную ?
 8. Какая разница между local и my ?
 9. Как использовать switch ?
 10.Как определить имя текущего модуля ?
 11.Как сделать большой блок комментариев ?
 12.Как удалить пакет в рантайме ?
 
 System Interaction 
 
 1.  Как узнать название операционной системы ?
 2.  Как раскрасить вывод ?
 3.  Как контролировать ввод с клавы ?
 4.  Как очистить экран ?
 5.  Как пользователю ввести пароль ?
 6.  Как работать с портами ?
 7.  Как запустить другой процесс 7
 8.  Как сделать паузу меньше секунды ?
 9.  Как обработать исключение ?
 10. Как захватить STDOUT, STDERR из внешней команды ?
 11. Как запустить команду без помощи шелла ?
 12. Можно ли использовать перл для  telnet или ftp session ?
 13. Как открыть файл без его блокировки ?
 14. Как проинсталлировать модуль CPAN ?
 15. Какая разница между require и use ?
 16. Как добавить новый каталог в список  module/library ?
 
 

Programming Tools

1. В: Как запустить интерактивный дебаг ?

О: Запустить из командной строки с ключом

 	perl -de 42
 
Можно проверить стек , переменные , установить точки прерывания

2. В: Как определить список модулей , установленных на системе ?

О: Для вывода всех установленных модулей :

 	use ExtUtils::Installed;
 	my $inst    = ExtUtils::Installed->new();
 	my @modules = $inst->modules();	
 
Для вывода имен файлов модулей :
 	use File::Find::Rule;
 	my @files = File::Find::Rule->file()->name( '*.pm' )->in( @INC );
 
Можно проверить наличие модуля по документации для него - если она есть :
 	prompt% perldoc Module::Name
 
Можно проверить наличие модуля из командной строки :
 	perl -MModule::Name -e1
 
3. В: Как выполнить дебаг программ ?

О: Использовать

 		use strict;
 		use warnings;
 
Использовать :
 		print
 
Использовать модуль Data::Dumper
 		use Data::Dumper qw( Dumper );
 		print STDERR "The hash is " . Dumper( \%hash ) . "\n";
 
4. В: Профайлинг

О: Использовать модуль Benchmark

 		use Benchmark;
 		timethese($count, { ... } )
 
На это будет выведен отчет

5. В: Среда

О: Еклипс , комодо , vi , emacs

6. В: Интеграция curses

О: На cpan имеется модуль для интеграции с перлом

7. В: Как ускорить работу перла ?

 
 О:  1. Оптимизация программных алгоритмов
 	2. Использование модулей AutoSplit , AutoLoader	
 	3. Интеграция с кодом на Си (например , cpan-ский модуль PDL написан на си)
 	4. Линковка к статическим библиотекам вместо расшаренных :
 		вместо libc.so -> libc.a
 
8. В: Как уменьшить затраты на память ?
 	
 О:  1. Использовать си-шные типы вместо аналогичных перловых , например массивы
 	2. Использовать битовые массивы вместо булевских
 	3. Использование системного malloc <-> встроенного перлового malloc
 	4. Читать большие файлы не целиком , а построчно
 	5. Не квотировать большие строки , т.е 
 		вместо my $copy = "$large_string";
 		нужно my $copy = $large_string;
 		т.к. в первом случае будет 2 копии , а во втором одна
 	6. Передавать массивы и хеши по ссылке , а не по значению 
 	7. Большие порции данных сбрасывать на диск
 
9. В: Можно ли возвращать из функции ссылку на локальную переменную ?

О: Можно - перловый GC ведет себя корректно :

 	sub makeone 
 	{
 		my @a = ( 1 .. 10 );
 		return \@a;
     }
 
     for ( 1 .. 10 ) 
 	{
         push @many, makeone();
     }		
 
10. В: Как увеличить скорость загрузки CGI-скриптов ?

О: Использовать модули mod_perl или mod_fastcgi В первом случае скрипт компилится и при каждом последующем выполнении не форкается. При этом mod_perl предоставляет перловым скриптам доступ к apache API Во втором случае каждый скрипт превращается в самостоятельного демона

11. В: Как закрыть исходники ?

 
 О:  1. Не давать прав на чтение при доступе из инета
 	2. Можно зашифровать исходники с помощью Filter::Simple и Filter::Util::Call 
 	3. Можно откомпилировать байт-код
 
12. В: Как откомпилировать перловый код в байт-код
 О:  1. Использовать Perl Archive Toolkit - аналог жабовского JAR
 	2. Использовать Perl Dev Kit - от ActivePerl
 	3. Perl2Exe
 
13. В: Литература по OOP Perl
 
 О:  1. Object-Oriented Perl - Damian Conway
 	2. Intermediate Perl    - Randal Schwartz
 	3. perldoc : perltoot, perlobj, perlboot, perltooc, and perlbot
 
14. В: Линковка Си и Perl
 
 О:  1. perldoc : perlxstut, perlxs, xsubpp, perlguts - вызов Си из Перл
 	2. perldoc : perlembed, perlcall, perlguts - вызов Перл из Си
 	3. Использовать модуль Inline::C - интеграция си-шного кода напрямую в перловый 
 
15. В: Как получить полный список ошибок в Перл
 
 О: 	 perldoc perldiag
 	В программе можно прописать     use diagnostics;
 
16. В: Что такое MakeMaker

О: Модуль ExtUtils::MakeMaker генерит из Makefile из Makefile.PL . Makefile уже используется для инсталяции перловых пакетов.

Data Manipulation

1. В: Как задать точность до знака после запятой в типе float ?

О: perldoc perlnumber Использовать функции printf или sprintf :

 		printf "%.2f", 10/3;
 		my $number = sprintf "%.2f", 10/3;	
 
2. В: Конвертация данных в 8- и 16-ричном формате

О: Использовать функции oct() и hex() для конвертации в десятичный формат .

 		$dec = hex("DEADBEEF");
 		$dec = oct("33653337357");
    		$decimal = oct( "0b$input" );	это 2-ное в 10-ное
    Наоборот - 10-е в 16-ричное :
 	    $hex = sprintf("%x", 3735928559); # lower case a-f
    Наоборот - 10-е в 8-ричное :
 		$oct = sprintf("%o", 3735928559);
    Наоборот - 10-е в 2-ричное :
 		$bin = sprintf("%b", 3735928559);
 
Восьмеричное число начинается с символа ноль , 16-ричное - с 0x.

3. В: Округление чисел

О: 1. Использовать printf

 		printf("%.3f", 3.1415926535);   # prints 3.142
 	2. Модуль POSIX включает функции ceil(), floor()
 		use POSIX;
 		$ceil   = ceil(3.5);   # 4
 		$floor  = floor(3.5);  # 3 
 
4. В: Как оперировать с матрицами

О: Использовать модули Math::Matrix , Math::MatrixReal

5. Как передать массив в функцию и вернуть результат в этот же массив

О: Использовать функцию map

 		@results = map { my_func($_) } @array;
 		@results = map { some_func($_) } (5 .. 25);
 
6. Как получить случайные числа в диапазоне 10-15
 
 О: my $number = 10 + int rand( 15-10+1 );
 
7. В: Работа с датами

О: Использовать модуль POSIX Для работы с форматированными датами использовать модули Date::Manip, Date::Calc, DateTime День и неделя в году

 	$day_of_year = (localtime)[7];
 	my $day_of_year  = strftime "%j", localtime;
 	my $week_of_year = strftime "%W", localtime;
 
Век :
 	return int((((localtime(shift || time))[5] + 1999))/100);
 
Вычислить вчерашнюю дату :
 	use DateTime;
 	my $yesterday = DateTime->now->subtract( days => 1 );
 
Или так :
 	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_time\n";	
 
8. В: Как проверять валидность данных

О: Смотрите модули , в которых присутствует "Assert" и "Validate". А также модули Regexp::Common, Business::ISBN, Business::CreditCard, Email::Valid, Data::Validate::IP и т.д.

9. В: Как удалить/заменить/посчитать повторяющиеся символы

О: Удаление :

 	1.  s/(.)\1/$1/g;
 	2. 	my $str = 'Russia'; 
 		$str =~ tr///cs; 
 
Замена : в общем случае нужно применять модификатор /g в цикле : Посчитать число повторов одного символа - в общем случае использовать модификатор tr/// : tr/a// или tr/b// Для повторяющейся группы символов надо использовать цикл.

10. В: Как работает substr

 
 О:   1. $string = "Just another Perl Hacker";
 		$first_char = substr( $string, 0, 1 );  #  'J'  
 	 2. substr( $string, 13, 4, "Perl 5.8.0" );
 	 3. substr( $string, 13, 4 ) =  "Perl 5.8.0";
 
11. В: Как подсчитать число вхождений подстроки в строку ?

О: Если нужно подсчитать число вхождений символа , нужно использовать модификатор 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";	
 
12. В: Как работает функция split ?

О: Можно сделать собственную реализацию split :

 	 $text = "1,2,3,4,5,6,7,8,9";
 	 @new = ();
 	 push(@new, $+) while $text =~ m{([^,]+),?}gx;
 	 push(@new, undef) if substr($text,-1,1) eq ',';
 	 Получим массив 1 2 3 4 5 6 7 8 9
 
Стандартный вариант решения :
 	 use Text::ParseWords;
 	 @new = quotewords(",", 0, $text);
 
Еще - получить массив из строки с разделителем пробел :
 		my $line    = ' fred barney   betty   ';
 		my @columns = split /\s+/, $line;
 
Еще - получить массив из строки с разделителем || :
 		my $line    = 'fred||barney||betty';
 		my @columns = split /\|/, $line;
 
13. В: Как удалить повторы из массива ?

О: Использовать хеш :

 	@array=(1,2,3,4,1,1,1,2,2,2,2,3,4,5,6,6,6,5,4,3,3,3,3);
 	my %hash   = map { $_, 1 } @array;
 	my @result_array = keys %hash;
 	foreach  $un (@result_array)
 	{
 		print "$un\n";
 	}
 
Второй вариант - использовать стандартный grep :
 	my @unique = grep { ! $seen{ $_ }++ } @array;
 
14. В: Как определить - есть ли в данном массиве данный элемент ?

О: Составить промежуточный массив индексов :

 	@primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
 	@is_tiny_prime = ();
 	for (@primes) { $is_tiny_prime[$_] = 1 }
 
или так :
 	@istiny_prime[@primes] = (1) x @primes;
 
Стандартный подход - для нахождения отдельного элемента :
 	my $is_there = grep $_ eq 17, @primes;
 
15. Как вычислить разницу или пересечение между двумя массивами ?

О: Использовать все тот же хеш :

 	@array1 = (1,2,3,4,5,6,7,8,9,10);
 	@array2 = (9,10,11,12,13,14,15,16);
 	@union = @intersection = @difference = ();
 	%count = ();
 	foreach $element (@array1, @array2) { $count{$element}++ }
 	foreach $element (keys %count) 
 	{
 		push @union, $element;
 		push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element;
 	}
 
16. В: Как проверить на эквивалентность 2 массива ?
 
 О:     $are_equal = compare_arrays(\@array1, \@array2);
 		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;
 		}
 
17. В: Как проверить - есть ли данный элемент в массиве ?

О: Стандартный подход :

 	use List::Util qw(first);
 	@array = ("Perl","Python","c++");
 	my $element = first { /Perl/ } @array;
 
Если нужно найти индекс искомого элемента в массиве
 	my( $found, $index ) = ( undef, -1 );
 		for( $i = 0; $i < @array; $i++ ) 
 		{
 			if( $array[$i] =~ /Perl/ ) 
 			{
 				$found = $array[$i];
 				$index = $i;
 				last;
 			}
 		}
 
18. В: Нужны ли связные списки в перле ?

О: В общем случае - нет. С помощью операций push , pop , shift ,unshift всегда можно добавить/удалить произвольный элемент массива.

19. В: Как отсортировать массив ?

О: Стандартным способом - при этом генерится новый массив :

 	use List::Util 'shuffle';
 	@shuffled = shuffle(@list);
 
Другой вариант :
 	@idx = (1,2,3,4,5,6,5,4,3)	;
 	@idx = sort { $a <=> $b } @idx;
 
20. В: Пусть имеется массив . Как составить все-возможные комбинации из его элементов ?
 
 О:	@idx = (1,2,3,4,5)	;
 	sub permute (&@) 
 	{
 			my $code = shift;
 			while ( $code->(@_[@idx]) ) 
 			{
 				my $p = $#idx;
 				--$p while $idx[$p-1] > $idx[$p];
 				my $q = $p or return;
 				push @idx, reverse splice @idx, $p;
 				++$q while $idx[$p-1] > $idx[$q];
 				@idx[$p-1,$q]=@idx[$q,$p-1];
 			}
 	}
 	permute {print"@idx\n"} split;
 
21. В: Как оперировать операциями над битами ?

О: Использовать pack() , unpack(), vec() плюс битовые операции :

 	$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(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";
 		}
 
22. В: Как работать с хешем ?

О: Вначале нужно получить ключи с помощью функции keys. Распечатка значений хеша :

 		foreach my $key ( keys %hash ) 
 		{
 			my $value = $hash{$key};
 			print "$value\n";
 		}
 
Можно отсортировать ключ :
 		foreach my $key ( sort keys %hash ) 
 		{
 			my $value = $hash{$key};
 			print "$value\n";
 			
 		}
 
Если хеш очень большой и не хочется в памяти создавать список ключей , можно использовать функцию each() :
 		while( my( $key, $value ) = each( %hash ) ) 
 		{
 			print "$value\n";
 		}
 
23. В: Можно ли в хеш добавлять-удалять ключ в момент итерации над этим хешем ?

О: Нельзя.

24. В: Как отыскать хеш по значению ?

О: Чтобы найти индекс по значению , надо сделать реверс :

 	%by_value = reverse %hash;
 	$key = $by_value{$value};
 
Можно распечатать и ключ , и значение в цикле , не используя дополнительных затрат памяти :
 	while (($key, $value) = each %hash) 
 	{
 		$by_value{$value} = $key;
 		print "$by_value{$value}\n";
 		print "$value\n";
 	}	
 
25. В: Как узнать число элементов хеша ?

О: Просто использовать keys() :

 		$num_keys = keys %hash;
 
26. В: В чем разница между функциями delete и undef для хеша ?

О: Первая удаляет из хеша пару ключ-значение , вторая присваивает значению = undef

27. В: Как получить уникальные ключи из 2-х хешей ?

О: Более простой , но и более затратный по памяти способ :

 	@uniq = keys %{{%hash,%hash2}};
 
Менее затратный по памяти способ :
 	%seen = ();
 	while (defined ($key = each %hash)) {
 		$seen{$key}++;
 	}
 	while (defined ($key = each %hash2)) {
 		$seen{$key}++;
 	}
 	@uniq = keys %seen;
 
28. Как в перле создать структуру , аналогичную си-шной по синтаксису ?

О: Используя хеш :

 	$record = {
 		NAME   => "Jason",
 		EMPNO  => 132,
 		TITLE  => "deputy peon",
 		AGE    => 23,
 		SALARY => 37000,
 		PALS   => [ "Norbert", "Rhys", "Phineas"],
 	};
 
29. В: Как определить тип скаляра ?
 
 О: 	$str = "123a";
 	if ($str =~ /\D/)            { print "has nondigits\n" }
 	if ($str =~ /^\d+$/)         { print "is a whole number\n" }
 	if ($str =~ /^-?\d+$/)       { print "is an integer\n" }
 	if ($str =~ /^[+-]?\d+$/)    { print "is a +/- integer\n" }
 	if ($str =~ /^-?\d+\.?\d*$/) { print "is a real number\n" }
 	if ($str =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/) { print "is a decimal number\n" }
 	if ($str =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) { print "a C float\n" }
 
30. В: Как сохранить данные между вызовами скрипта ?

О: Использовать модуль Storable - при этом происходит кеширование данных на диск в файл:

 		use Storable;
 		store(\@array, "filename");  # сохранили в файл
 		@array3 = @{ retrieve("filename") };   # извлекли из файла
 
31. В: Как можно использовать класс UNIVERSAL ?

О: Его можно использовать для определения того , унаследован ли какой-то обьект от какого-то типа , с помощью метода isa , напр :

 		use UNIVERSAL "isa";
 		$ref = [1, 2, 3];
 		if (isa($ref, 'ARRAY')) {
 		print "OK\n";
 		
 		} else {
 		print "Not OK\n";
 		}
 
Метод can класса UNIVERSAL позволяет осуществлять проверку того, имеет ли класс или объект метод с указанным именем (имя метода задано в виде текстовой строки). Если такого метода нет, возвращается значение ложь. Если метод найден, возвращается ссылка на метод. Пример:
 		$datacall = $object->can('getdata');
 		if ($datacall) ...
 

Files

1. В: Как изменить , удалить или добавить строку в файл ?

О: В примере читается текстовой файл и создается его клон :

 	open my $in,  '<',  "filename"      or die "Can't read old file: $!";
 	open my $out, '>', "filename.new" or die "Can't write new file: $!";
 	while( <$in> )
 		{
 		print $out $_;
 		}
     close $in;
     close $out;
 
То же самое , но в клон будет добавлена новая строка в начале файла :
 	open my $in,  '<',  "filename"      or die "Can't read old file: $!";
 	open my $out, '>', "filename.new" or die "Can't write new file: $!";
 	print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC
 	while( <$in> )
 		{
 			print $out $_;
 		}
     close $in;
     close $out;	
 
То же самое , но в исходном файле проверяются строки на наличие подстроки "Perl" , и в клоне она будет заменена на "perl"
 	open my $in,  '<',  "filename"      or die "Can't read old file: $!";
 	open my $out, '>', "filename.new" or die "Can't write new file: $!";
 	print $out "# Add this line to the top\n";
 	while( <$in> )
 		{
 			s/\b(Perl)\b/perl/g;
 			print $out $_;
 		}
     close $in;
     close $out;
 
Следующий код заменяет произвольную - 5-ю по счету - строку в клон-файле :
 	open my $in,  '<',  "filename2"      or die "Can't read old file: $!";
 	open my $out, '>', "filename2.new" or die "Can't write new file: $!";
 	while( <$in> )   # print the lines before the change
 	{
 		print $out $_;
 		last if $. == 4; # line number before change
 	}
 	my $line = <$in>;
 	print $out "555555555555\n";
 	while( <$in> )   # print the rest of the lines
 	{
 		print $out $_;
 	}
     close $in;
     close $out;
 
Следующий код пропустит при клонировании каждую 5-ю строку :
 	open my $in,  '<',  "filename3"      or die "Can't read old file: $!";
 	open my $out, '>', "filename3.new" or die "Can't write new file: $!";
 
 		while( <$in> )
 		{
 		next unless $. % 5;
 		print $out $_;
 		}
     close $in;
     close $out;
 
Следующая команда перезаписывает inFile.txt , меняя при этом Fred на Barney
 	perl -pi -e 's/Fred/Barney/' inFile.txt
 	Back-up для файла inFile.txt :
 	perl -pi.bak -e 's/Fred/Barney/' inFile.txt
 
Вставка строки в определенное место :
 	perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt
 
Вставить строку в начало файла :
 	perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt
 
Вставить строку в определенную позицию :
 	perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt
 
Для удаления строк :
 	perl -ni -e 'print unless /d/' inFile.txt
 
В следующем примере используется опция -i. В текущем каталоге будут модифицированы все файлы с расширением .new путем добавления в начало файла новой строки , при этом старый файл будет сохранен с расширением .orig
 	local($^I, @ARGV) = ('.orig', glob("*.new"));
 	while (<>) {
 		if ($. == 1) {
 			print "This line should appear at the top of each file\n";
 		}
 		s/\b(p)earl\b/${1}erl/i;        # Correct typos, preserving case
 		print;
 		close ARGV if eof;              # Reset $.
 		}
 
2. В: Как подсчитать число строк в файле ?
 
 О:  $lines = 0;
 	open(FILE, "filename") or die "Can't open `$filename': $!";
 	while (sysread FILE, $buffer, 4096) {
 		$lines += ($buffer =~ tr/\n//);
 		}
 	close FILE;
 
3. В: Как скопировать файл ?
 
 О: 	use File::Copy;
 	copy( "filename1", "filename2" ) or die "Copy failed: $!";
 
4. В: Как обращаться с хенлами файлов на процедурном уровне в качестве параметров ?

О: Ссылку на файл можно передавать как на любой другой скаляр :

 	open my    $fh, $file_name;
 	open local $fh, $file_name;
 	print $fh "Hello World!\n";
 	process_file( $fh );
 
Их можно размещать в массив и оперировать с ним :
 	my @fhs = ( $fh1, $fh2, $fh3 );
 	for( $i = 0; $i <= $#fhs; $i++ ) 
 	{
 		print {$fhs[$i]} "just another Perl answer, \n";
 	}
 
5. В: Можно ли использовать файловый хендл косвенно ?

О: Можно :

 		$fh =   SOME_FH;       # bareword is strict-subs hostile
 		$fh =  "SOME_FH";      # strict-refs hostile; same package only
 		$fh =  *SOME_FH;       # typeglob
 		$fh = \*SOME_FH;       # ref to typeglob (bless-able)
 		$fh =  *SOME_FH{IO};   # blessed IO::Handle from *SOME_FH typeglob
 
Можно использовать IO::Handle для создания скаляра :
 		use IO::Handle;                     
 		$fh = IO::Handle->new();
 
Косвенный файл-хендл - это скаляр. Для передачи файл-хендла в функцию :
 		sub accept_fh 
 		{
 			my $fh = shift;
 			print $fh "Sending to indirect filehandle\n";
 		}	
 
Примеры неправильного использования скаляра :
 		@fd = (*STDIN, *STDOUT, *STDERR);
 		print $fd[1] "Type it: ";                           # WRONG
 		$got = <$fd[0]>                                     # WRONG
 		print $fd[2] "What was that: $got";                 # WRONG		
 
Примеры правильного использования скаляра :
 		print  { $fd[1] } "funny stuff\n";
 		printf { $fd[1] } "Pity the poor %x.\n", 3_735_928_559;
 
6. В: Как открыть файл на чтение-запись ?

О: На чтение :

 		use Fcntl;
 		open(FH, "< $path")  || die $!;
 		sysopen(FH, $path, O_RDONLY)       	
 
На запись :
 		open(FH, "> $path") || die $!;
 		sysopen(FH, $path, O_WRONLY|O_TRUNC|O_CREAT)        || die $!;
 		sysopen(FH, $path, O_WRONLY|O_TRUNC|O_CREAT, 0666)  || die $!;
 
Открыть файл для добавления в конец :
 		open(FH, ">> $path") || die $!;
 		sysopen(FH, $path, O_WRONLY|O_APPEND|O_CREAT)       || die $!;
 		sysopen(FH, $path, O_WRONLY|O_APPEND|O_CREAT, 0666) || die $!;
 
Открыть файл для апдэйта - если он существует :
 		open(FH, "+< $path")                                || die $!;
 		sysopen(FH, $path, O_RDWR)                          || die $!;
 
Открыть файл для апдэйта - если он не существует :
 		sysopen(FH, $path, O_RDWR|O_CREAT)                  || die $!;
 		sysopen(FH, $path, O_RDWR|O_CREAT, 0666)            || die $!;
 
7. В: Как переименовать файл ?
 О:  rename($old, $new) or system("mv", $old, $new);
 
8. В: Как открыть текстовой файл , прочитать оттуда число , сделать инкремент и записать результат в файл ?
 
 О: 	sysopen(FH, "filename", O_RDWR|O_CREAT) 	 or die "can't open numfile: $!";
 	flock(FH, LOCK_EX) 				 or die "can't flock numfile: $!";
 	$num =  || 0;
 	seek(FH, 0, 0) 				 or die "can't rewind numfile: $!";
 	truncate(FH, 0) 				 or die "can't truncate numfile: $!";
 	(print FH $num+1, "\n")			 or die "can't write numfile: $!";
 	close FH 			
 
9. В: Как изменить бинарный файл ?

О: Можно просто :

 	perl -i -pe 's{window manager}{window mangler}g' /usr/bin/emacs
 
Если размер бинарника фиксирован :
 	$RECSIZE = 220; # size of record, in bytes
 	$recno   = 37;  # which record to update
 	open(FH, "+< somewhere") || die "can't update somewhere: $!";
 	seek(FH, $recno * $RECSIZE, 0);
 	read(FH, $record, $RECSIZE) == $RECSIZE || die "can't read record $recno: $!";
 	# munge the record
 	seek(FH, -$RECSIZE, 1);
 	print FH $record;
 	close FH;
 
10. В: Как получить время изменения файла ?
 
 О:  $write_secs = (stat($file))[9];
 	printf "file %s updated at %s\n", $file,
 	scalar localtime($write_secs);
 
Или так :
 	use File::stat;
 	use Time::localtime;
 	$date_string = ctime(stat($file)->mtime);
 	print "file $file updated at $date_string\n";
 

Regular Expressions

1. В: В каком стиле лучше писать регеспы ?

О: Рассмотрим пример :

 	s{<(?:[^>'"]*|".*?"|'.*?')+>}{}gs;
 
С помощью модификатора /x его можно привести к виду :
 	s{ <                    # открытие угловых скобок
 		(?:                    # Non-backreffing grouping paren
 			[^>'"] *        # 0 or more things that are neither > nor ' nor "
 				|              #    or else
 			".*?"              # a section between double quotes (stingy match)
 				|              #    or else
 			'.*?'              # a section between single quotes (stingy match)
 		) +                    #   all occurring one or more times
 		>                   # closing angle bracket
 	}{}gsx;                    # replace with nothing, i.e. delete
 
В качестве разделителя как правило используется символ /. Иногда удобно применить другую комбинацию :
 	s/\/usr\/local/\/usr\/share/g;	# не очень понятно
 	s#/usr/local#/usr/share#g;		# лучше
 
Если вывод не влезает на одну строку , можно применить модификатор /m , который поддерживает перевод строки. Например , в следующем примере мы ищем повторы слов несмотря на то , что возможны переводы строк.
 		$/ = '';  		# read in more whole paragraph, not just one line
 		while ( <> ) 
 		{
 			while ( /\b([\w'-]+)(\s+\1)+\b/gi ) 
 			{  	# word starts alpha
 				print "Duplicate $1 at paragraph $.\n";
 			}
 		}
 
Следующий код находит строку начинающуюся со слова 'From'
 	$str = 'From 123';  		# read in more whole paragraph, not just one line
 	while ( /^From /gm ) 
 	{ # /m makes ^ match next to \n
 		print "leading from in paragraph $.\n";
 	}
 
Следующий код выводит содержимое параграфа , заключенного между START - END
 		$str="START 1
 		2
 		3
 		END";
 		while ($str =~ /START(.*?)END/sgm ) 
 		{ # /s makes . cross line boundaries
 		    print "$1\n";
 		}
 
2. В: Как сделать , чтобы работала русская локаль для \w match ?

О: Использовать русскую локаль с помощью use locale; Что-то типа

 	setlocale(LC_CTYPE, 'ru_RU.CP1251'); 
 	Смотрите perldoc perllocale
 
3. В: Как квотировать переменную внутри регеспа ?

О: В следующем примере символ 4 в строке будет заменен на набор четверок :

 	$string = "123 456 789";
 	$regex  = "4";
 	$string =~ s/$regex/44444/;
 
4. В: Можно ли отдебажить регулярное выражение ?

О: Можно. Нужно использовать

 	use re 'debug';
 	Пример 
 		use re 'debug';
 		$regex = 'Perl';
 		foreach ( qw(Perl Java Ruby Python) ) 
 		{
 			print STDERR "Trying $_...\n";
 			print STDERR "\t$_ is good!\n" if m/$regex/;
 		}
 
5. В: Как вырезать из файла комменты в стиле си ?

О: Например так :

 	perl -0777 -pe 's{/\*.*?\*/}{}gs' foo.c
 
6. В: Как правильно использовать т.н. квантификаторы - quantifiers (?, *, +, {}) ?

О: Квантификатор *? находит первое вхождение :

 	$s1 = $s2 = "I am very very cold";
 	$s1 =~ s/ve.*y //;      # I am cold
 	$s2 =~ s/ve.*?y //;     # I am very cold
 
7. В: Как работает \b ?

О: Пример :

 	"Perl"    # no word char before P or after l
 	"Perl "   # same as previous (space is not a word char)
 	"'Perl'"  # the ' char is not a word char
 	"Perl's"  # no word char before P, non-word char after "l"
 	Все эти 4 варианта эквивалентны /\bPerl\b/.
 
Следующие 2 строки соответствуют /\Bam\B/:
 	"llama"   # "am" surrounded by word chars
 	"Samuel"  # same
 
Следующие 2 строки не соответствуют /\Bam\B/
 	"Sam"      # no word boundary before "a", but one after "m"
 	"I am Sam" # "am" surrounded by non-word chars
 
8: В: Где можно применять \G ?

О: Он используется для позиционирования.

 	Пример :
 	$_ = "1122a44";
 	my @pairs = m/(\d\d)/g ;   # qw( 11 22 44 )
 	print "@pairs\n";
 	Здесь  /g позволяет вычислить все пары чисел , в том числе и после символа a.
 	Если так :	
 	my @pairs = m/\G(\d\d)/g; # qw( 11 22 )
 	или так :
 	while( m/\G(\d\d)/g )
 		{
 		print "Found $1\n";
 		}
 	то будут вычислены пары до символа a.
 

General Perl Language Issues

1. В: Каковы основные спецификаторы типов :
 О: 	$ - числа , строки 
 	@ - массивы
 	% - хеши
 	& - функции , процедуры , методы
 	* - указатели 
 	<> - содержимое файла
 	\  - ссылка
 
2. В: Как проигнорировать возвращаемые значения ?
 
 О:  Использовать undef.
 	Пример :
 	($dev, $ino, undef, undef, $uid, $gid) = stat($file);
 	Или использовать список параметров :
 	($dev, $ino, $uid, $gid) = ( stat($file) )[0,1,4,5];
 
3. В: Можно ли блокировать варнинги ?
 
 О: Можно
 	{
 		no warnings;          # temporarily turn off warnings
 		$a = $b + $c;         # I know these might be undef
 	}
 
4. В: Что такое extension ?

О: Это вызов скомпилированного си-шного кода из перл См. perldoc perlxstut 5. В: Как создать структуру ?

О: Используйте хеш / ссылку на хеш :

 	$person = {};                   # new anonymous hash
 	$person->{AGE}  = 24;           # set field AGE to 24
 	$person->{NAME} = "Nat";        # set field NAME to "Nat"	 
 
6. В: Как передать - и - вернуть из функции такие обьекты , как : Function, FileHandle, Array, Hash, Method, Regex ?

О: Смотрите perldoc perlsub , раздел Pass by Reference , также perldoc perlref. Стандартный тип переменной или функцию вертать просто - передавайте ссылку :

 	func( \$some_scalar );
 	func( \@some_array  );
 	func( [ 1 .. 10 ]   );
 	func( \%some_hash   );
 	func( { this => 10, that => 20 }   );
 	func( \&some_func   );
 	func( sub { $_[0] ** $_[1] }   );	
 	Для передачи filehandle нужно использовать скаляр :
 	open my $fh, $filename or die "Cannot open $filename! $!";
 	func( $fh );
 	sub func {
 		my $passed_fh = shift;
 		my $line = <$passed_fh>;
 		}	
 
Для передачи в функцию регеспа нужно , чтобы поддерживалась конструкция qr//. В следующем примере в строке ищатся буквы d в обоих регистрах :
 	sub compare($$) 
 	{
 		my ($val1, $regex) = @_;
 		my $retval = $val1 =~ /$regex/;
 		return $retval;
 	}
 	$match = compare("oldD Mconald", qr/d.*D/i);
 
Для передачи метода обьекта нужно делать примерно так :
 	call_a_lot(10, $some_obj, "methname")
 	sub call_a_lot {
 		my ($count, $widget, $trick) = @_;
 		for (my $i = 0; $i < $count; $i++) {
 			$widget->$trick();
 		}
 	}
 
7. В: Как создать статическую переменную ?

О: В перле нет статических переменных , есть лексические переменные , которые видимы внутри блока кода либо внутри одного файла .

 	BEGIN {
 			my $count = 1;
 			sub increment_count { $count++ }
 			sub return_count    { $count }
 		}
 
 		Смотрите Persistent Private Variables в perlsub		
 
8. В: Какая разница между local и my ?

О: local присваивает значение уже существующей переменной , находящейся в пределах видимости my создает новую переменную

 	Пример :
 	sub visible {
 		print "$var\n";
 		}
 	sub dynamic {
 		local $var = 'local';	# new temporary value for the still-global
 		visible();              #   variable called $var
 		}
 	sub lexical {
 		my $var = 'private';    # new private variable, $var
 		visible();              # (invisible outside of sub scope)
 		}
 	$var = 'global';
 	visible();      		# prints global
 	dynamic();      		# prints local
 	lexical();      		# prints global
 
9. В: Как использовать switch ?
 О:  Пример :
 		$variable_to_test=2;
 		for ($variable_to_test) 
 		{
 			if    (/1/)  { print"1\n"; }     # do something
 			elsif (/2/)  { print"2\n";}     # do something else
 			elsif (/3/)  { print"3\n";}     # do something else
 			else            { }     # default
 		}
 
10. В: Как определить имя текущего модуля ?
 
 О:  my $packname = __PACKAGE__;
 
11. В: Как сделать большой блок комментариев ?

О: Нужно оформить блок :

 =begin
 
 	...
 
 =cut
 
12. В: Как удалить пакет в рантайме ?
 
 О: Пример :
 	sub scrub_package 
 	{
 		no strict 'refs';
 		my $pack = shift;
 		die "Shouldn't delete main package"
 			if $pack eq "" || $pack eq "main";
 		my $stash = *{$pack . '::'}{HASH};
 		my $name;
 		foreach $name (keys %$stash) 
 		{
 			my $fullname = $pack . '::' . $name;
 			# Get rid of everything with that name.
 			undef $$fullname;
 			undef @$fullname;
 			undef %$fullname;
 			undef &$fullname;
 			undef *$fullname;
 		}
 	}	
 

System Interaction

1. В: Как узнать название операционной системы ?
 
 О:  $^O
 
2. В: Как раскрасить вывод ?
 
 О:  use Term::ANSIColor;
 	print color("red"), "Stop!\n", color("reset");
 	print color("green"), "Go!\n", color("reset");
 	Или так :
 	use Term::ANSIColor qw(:constants);
 	print RED, "Stop!\n", RESET;
 	print GREEN, "Go!\n", RESET;
 
3. В: Как контролировать ввод с клавы ?
 
 О:  Использовать stty :
 	open(TTY, "+/dev/tty 2>&1";
 	$key = getc(TTY);		# perhaps this works
 	# OR ELSE
 	sysread(TTY, $key, 1);	# probably this does
 	system "stty -cbreak /dev/tty 2>&1";
 	Или так :
 	use Term::ReadKey;
 	ReadMode('cbreak');
 	$key = ReadKey(0);
 	ReadMode('normal');
 
4. В: Как очистить экран ?
 
 О: 	system("clear");
 
5. В: Как пользователю ввести пароль ?
 
 О: 	use Term::ReadKey;
 	ReadMode('noecho');
 	$password = ReadLine(0);
 
6. В: Как работать с портами ?

О: Это зависит от ОС. Для юникса нужно использовать /dev. При этом могут возникнуть проблемы с lockfiles из-за множественного доступа. Порт нужно открыть на апдэйт - см. open , perlfunc. Используйте sysopen() , флаг O_RDWR|O_NDELAY|O_NOCTTY. Для вывода символов нужно использовать select() и переменную $| для контроля autoflushing.

 	$oldh = select(DEV);
 	$| = 1;
 	select($oldh);
 	или так 
 	use IO::Handle;
 	DEV->autoflush(1);
 	Для non-blocking input можно использовать код :
 	sub open_modem 
 	{
 		use IPC::Open2;
 		my $stty = `/bin/stty -g`;
 		open2( \*MODEM_IN, \*MODEM_OUT, "cu -l$modem_device -s2400 2>&1");
 		# starting cu hoses /dev/tty's stty settings, even when it has
 		# been opened on a pipe...
 		system("/bin/stty $stty");
 		$_ = ;
 		chomp;
 		if ( !m/^Connected/ ) {
 			print STDERR "$0: cu printed `$_' instead of `Connected'\n";
 		}
 	}	
 
7. В: Как запустить другой процесс 7
 
 О: IPC::Open3, Parallel::Jobs, IPC::Run , POE
    Или
 	system("cmd &") 	
    или fork - смотрите fork , perlfunc, perlipc.
 
При этом STDIN, STDOUT , STDERR окажутся расшаренными для обоих процессов. Прийдется обрабатывать сигналы SIGCHLD ,SIGPIPE , когда запущенный процесс завершится.

8. В: Как сделать паузу меньше секунды ?

О: Используйте select() - см. perlfunc , select.

9. В: Как обработать исключение ?

 
 О:  Использовать блок END , например :
 	END {
 			close(STDOUT) || die "stdout close failed: $!";
 		}	
 	Можно использовать eval() - см. Signals , perlipc.
 	Можно использовать библиотеку exceptions.pl.
 
10. В: Как захватить STDOUT, STDERR из внешней команды ?
 
 О:  	STDOUT :
 	use IPC::Open3;
 	use File::Spec;
 	use Symbol qw(gensym);
 	open(NULL, ">", File::Spec->devnull);
 	my $pid = open3(gensym, \*PH, ">&NULL", "cmd");
 	while(  ) { }
 	waitpid($pid, 0);
 		STDERR :
 	use IPC::Open3;
 	use File::Spec;
 	use Symbol qw(gensym);
 	open(NULL, ">", File::Spec->devnull);
 	my $pid = open3(gensym, ">&NULL", \*PH, "cmd");
 	while(  ) { }
 	waitpid($pid, 0);
 		И STDOUT , и STDERR :
 	use IPC::Open3;
 	use Symbol qw(gensym);
 	use IO::File;
 	local *CATCHOUT = IO::File->new_tmpfile;
 	local *CATCHERR = IO::File->new_tmpfile;
 	my $pid = open3(gensym, ">&CATCHOUT", ">&CATCHERR", "cmd");
 	waitpid($pid, 0);
 	seek $_, 0, 0 for \*CATCHOUT, \*CATCHERR;
 	while(  ) {}
 	while(  ) {}
 
11. В: Как запустить команду без помощи шелла ?

О: Нужно использовать open() с набором аргументов . В следующем коде в искомом файле ищется подстрока :

 	$search_string="123";
 	@filenames=("filename");
 	open( GREP, "-|", 'grep', @opts, $search_string, @filenames );
 	chomp(@ok = );
 	close GREP;
 
12. В: Можно ли использовать перл для telnet или ftp session ?

О: Можно так смоделировать телнет :

 	use IO::Socket;             # new in 5.004
 	$handle = IO::Socket::INET->new('www.perl.com:80')
 	    or die "can't connect to port 80 on www.perl.com: $!";
 	$handle->autoflush(1);
 	if (fork()) {               # XXX: undef means failure
 	    select($handle);
 	    print while ;    # everything from stdin to socket
 	} else {
 	    print while <$handle>;  # everything from socket to stdout
 	}
 	close $handle;
 	exit;
 
13. В: Как открыть файл без его блокировки ?

О: Использовать флаги O_NDELAY , O_NONBLOCK

 	use Fcntl;
 	sysopen(FH, "/foo/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644)
 		or die "can't open /foo/somefile: $!":
 
14. В: Как проинсталлировать модуль CPAN ?
 
 О:  Стандарным путем :
 	$ perl -MCPAN -e shell
 	cpan shell -- CPAN exploration and modules installation (v1.59_54)
 	ReadLine support enabled
 	cpan> install Some::Module	
 	Или вручную :
 	   1 Распаковать архив
 	   2. 	perl Makefile.PL
 	   3.  	make
 	   4.  	make test
 	   5.  	make install
 
15. В: Какая разница между require и use ?
 	
 О:  1)  do $file is like eval `cat $file`, except the former
 	1.1: searches @INC and updates %INC.
 	1.2: bequeaths an *unrelated* lexical scope on the eval'ed code.
 
 	2)  require $file is like do $file, except the former
 	2.1: checks for redundant loading, skipping already loaded files.
 	2.2: raises an exception on failure to find, compile, or execute $file.
 
 	3)  require Module is like require "Module.pm", except the former
 	3.1: translates each "::" into your system's directory separator.
 	3.2: primes the parser to disambiguate class Module as an indirect object.
 
 	4)  use Module is like require Module, except the former
 	4.1: loads the module at compile time, not run-time.
 	4.2: imports symbols and semantics from that package to the current one.
 
16. В: Как добавить новый каталог в список module/library ?
 
 О:  use lib $directory;
 
Оставьте свой комментарий !

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

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