Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 MINIX...3057 
 Solaris...2933 
 LD...2906 
 Linux Kernel 2.6...2487 
 William Gropp...2182 
 Rodriguez 6...2017 
 C++ Templates 3...1946 
 Trees...1938 
 Kamran Husain...1866 
 Secure Programming for Li...1792 
 Максвелл 5...1711 
 DevFS...1695 
 Part 3...1684 
 Stein-MacEachern-> Час...1632 
 Go Web ...1627 
 Ethreal 4...1619 
 Стивенс 9...1607 
 Arrays...1607 
 Максвелл 1...1593 
 FAQ...1539 
 
  01.01.2024 : 3621733 посещений 

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;
 
Оставьте свой комментарий !

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

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