五 |
|
級 |
Записки проperl
Задачка
citeесть 2 бесконечно больших текстовых файла отсортированных лексикографически.br /Нужно найти разницу и записать в файлы./citebr /a name=cutid1/abr /precode
open A, shift or die;
open B, shift or die;
my $h = 0;
while (!(eof(A) eof(B)) ) {
( $a, $b ) = $h == 0 ?
( scalar lt;Agt;, scalar lt;Bgt; ) : $h == 1 ?
( $a, scalar lt;Bgt; ) : ( scalar lt;Agt;, $b );
print lt; $a and next unless (defined $b);
print gt; $b and next unless (defined $a);
$h = $a cmp $b or next;
print $h == 1 ? gt; $b : lt; $a;
}
/code/prebr /в принципе, можно сократить 2 строчки, но было лень разбираться с code$h = $a cmp $b or next;/code...br /img src=http://arto.homeunix.org/cgi/track.pl?diff /br /a name=cutid1-end/a
Категории: Друзья
Look-Around Assertions в операторе s///
До сих пор не задумывался на эту тему, но работает. Пример:br /citeЗадание: Удалить все знаки «+», за которыми следует цифра./citebr /precode
# perl -le $ARGV[0] =~ s#\+(?=\d)##g print $ARGV[0] +test + +12 +13 ++
+test + 12 13 ++
#
/code/prebr /img src=http://arto.homeunix.org/images/psilocybin.jpg /
Категории: Друзья
Задачка про CIDR
a href=http://nponeccop.livejournal.com/225261.html?style=mineОтсюда/a:br /citeЗадача такова: есть ASCIIZ-строка с IP-адресом, надо вернуть true, если этот адрес попадает в один из диапазонов, перечисленных в файле.br /br /Файл текстовый такого формата,br /br /192.168.1.3,192.168.1.5br /192.168.2.4,193.0.0.3br /br /Файл не отсортирован, дипапазоны произвольные и могут пересекаться. Первый адрес меньше второго или равен ему. Пересечение диапазонов можно обрабатывать двумя путями: лиюо отказываться грузить такой файл и выдавать что с чем пересеклось, либо не отказываться и корректно работать в таких условиях.br /br /Файл грузится один раз и потом десятки миллионов раз лукапится. Записей в конфиге - сотни./citebr /a name=cutid1/abr /Решение:br /precode
# cat gt; z.pl
#! /usr/bin/perl
use Net::Patricia;
use Net::CIDR::Lite;
my $pt = new Net::Patricia;
my $cidr = new Net::CIDR::Lite;
open F, shift or die;
while (f) {
chomp; s#,#-#;
foreach my $m ($cidr-gt;add_range($_)-gt;list) { $pt-gt;add_string($m) }
}
foreach (lt;gt;) {
chomp;
print $_, :, $pt-gt;match_string($_) ? YES : NO, \n;
}
^D
# perl z.pl /tmp/ip.range =( print -l 192.168.1.1 192.168.1.4 )
192.168.1.1:NO
192.168.1.4:YES
# perl -le foreach (0..$ARGV[0]) { printf %d.%d.%d.%d\n, rand()%255, rand()%255, rand()%255, rand()%255 } 10240000 gt;| /tmp/ip.list
# wc -l /tmp/ip.list
10240001 /tmp/ip.list
# time perl z.pl /tmp/ip.range /tmp/ip.list gt;| /dev/null
Real: 120.10s User: 105.21s System: 1.31s Percent: 88%% Cmd: perl z.pl /tmp/ip.range /tmp/ip.list gt;| /dev/null
#
/code/prebr /br /PS. Вкралась ошибка: неправильно сгенерил список ip адресов, надоbr /precode# perl -le foreach (0..$ARGV[0]) { printf %d.%d.%d.%d\n, int(rand(255)), int(rand(255)), int(rand(255)), int(rand(255)) } 10240000 gt;| /tmp/ip.list/code/prebr /Результат:br /precode# time perl z.pl /tmp/ip.range /tmp/ip.list gt;| /dev/null
Real: 176.98s User: 153.23s System: 2.20s Percent: 87%% Cmd: perl z.pl /tmp/ip.range /tmp/ip.list gt;| /dev/null/code/prebr /br /PS2. Скорость слабо зависит от количества сетей:br /precode
# for i in {1..300}; do a=$[ $RANDOM%255 ]; b=$[ $RANDOM%255 ]; c=$[ $RANDOM%254 ]; d=$[ $RANDOM%254 ]; print $a.$b.$c.$d,$a.$b.$[$c+1].$[$d+1]; done gt;| /tmp/ip.range2
# time perl z.pl /tmp/ip.range2 /tmp/ip.list gt;| /dev/null
Real: 187.54s User: 173.13s System: 1.98s Percent: 93%% Cmd: perl z.pl /tmp/ip.range2 /tmp/ip.list gt;| /dev/null
#
/code/prebr /a name=cutid1-end/a
Категории: Друзья
Версия пакета в package.
Можно теперь писать так:br /precode
package Package 1.23;
...
print $VERSION, \n;
...
1;
/code/prebr /Но версия в таком операторе не вычисляется, там надо писать именно число.br /Т.е. такое выражение даст ошибку:br /precode
package Package qw$Revision: 1.23 $[1];
/code/pre
Категории: Друзья
разбор ini-файла
Простейший ini-файл:br /br /codepre
# Comment
Param1 = Value1
[Section1]
Param2 = Value2
LongParam = Very \
Long \
Param
[Section2]
Param3 = Value3
/code/prebr /br /a name=cutid1/abr /codepre
# perl -MData::Dumper -0777 -lne s#\#.*?\n##gm; s#\\\n\s+##gsm; my $sect = __DEFAULT__;
while (m#(?:(?name\w+)\s*=\s*(?value.+?)\s+$|\[(?sect\w+)\])#gm) {
$sect = $+{sect} || $sect; $hash{$sect}-gt;{$+{name}} = $+{value} if exists $+{name}
} print Dumper \%hash /tmp/a.ini
$VAR1 = {
Section1 =gt; {
LongParam =gt; Very Long Param
},
Section2 =gt; {
Param3 =gt; Value3
},
__DEFAULT__ =gt; {
Param1 =gt; Value1
}
};
#
/pre/codebr /br /Или в виде функции:br /br /codepre
sub ini ($) {
local $_ = do { local $/; open F, $_[0] and f };
s#\#.*?\n##gm; s#\\\n\s+##gsm;
my $sect = __DEFAULT__;
my %hash;
while (m#(?:(?name\w+)\s*=\s*(?value.+?)\s+$|\[(?sect\w+)\])#gm) {
$sect = $+{sect} || $sect;
$hash{$sect}-gt;{$+{name}} = $+{value} if exists $+{name}
}
return \%hash;
}
/pre/codebr /a name=cutid1-end/a
Категории: Друзья
