Александр Яковлев a.k.a. Oreolek

19 Август 2010 г.

Perl: перегоняем строку в массив символов

Filed under: Perl — Александр Яковлев @ 00:42

Довольно часто хочется работать со строкой как с массивом символов. Но в Perl это – две разные вещи. Как же получить из одного другое?

Чаще всего рекомендуют следующий способ:

@array = split(//, $string);

Его легко написать и понять. Действительно, если передать функции split //, undef или пустой символ в качестве разделителя, то она разобьёт строку на массив символов. Вопрос исчерпан?

Вы забываете, о каком языке мы говорим. Это Perl, а значит – есть ещё способы сделать это.

@array = unpack("C*", $string);

Здесь всё также понятно, просто и быстро. Но если вы – фанат регэкспов, то следующий кусочек кода вам понравится чуть больше:

while (/./g) {...}

Точка в регулярном выражении означает любой символ (кроме новой строки). Чтобы точка ловила и символы новой строки, нужно добавить опцию /g к выражению.

Внутри цикла вы можете использовать переменную $1, где будет храниться текущий символ. Это действительно удобно, потому что решает не саму проблему, а её причину, позволяя работать со строкой посимвольно. Можно также использовать функции index и substr, но я не буду приводить примеров, они похожи.

Чуть проще записать следующее:

@array = ($string =~ /./g)

Это только основные способы, их можно комбинировать для совершенной эзотерики :-)

04 Август 2009 г.

Perl и преобразование регистра

Filed under: Perl — Александр Яковлев @ 09:34

Недавно хорошо промучился с преобразованием регистра в Perl. Дело в том,что Perl и Юникод не на короткой ноге, поэтому простым путём lc() ничего сразу не получится. Вот как следует преобразовывать в нижний регистр строку с Юникод-терминала:

#!/usr/bin/perl -wuse strict;use Encode;chomp(my $input = <STDIN>);my $string = decode("UTF-8",$input);$string = lc($string);print encode("UTF-8",$string);

Я был удивлён,что совершенно не требуется прагма use locale. Наоборот, при её использовании всё только ухудшается.Также существуют функции decode_utf8 и encode_utf8, которые принимают только один параметр; работают аналогично.Юникод – двухбайтовая кодировка, и требует подобного обращения при любом использовании. В конце хочу добавить,что замечание интерпретатора «Wide character in print at …» сигнализирует о том,что вы забыли закодировать строку обратно в UTF-8, и выводите её на экран во внутренней кодировке (попробуйте заменить последнюю строку на обычный print $string).

28 Июнь 2009 г.

Небольшой скрипт

Filed under: Perl — Александр Яковлев @ 12:28

Вчера была очередная игра, но я не об этом.
Я написал скрипт для того,чтобы обновлять внешний IP’шник в своём DC++. Предполагается linuxdcpp последних версий. Сильно, думаю, упростит жизнь людям с динамическим IP. Перед использованием проверьте переменные $path и $url

#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple; #получение IP
my $path = «.dc++/DCPlusPlus.xml»;#местонахождение собственно конфига
my $url = «http://p2p.kuzbass.net/getip.php»;#адрес, с которого берётся IP. Подойдёт любой стабильный и простой по выводу, как http://whatismyip.ru или http://whatismyip.org. Основной критерий, конечно же, стабильность.
my $ip = get($url) or die($!);
$ip =~ /(\d+.\d+.\d+.\d+)/; $ip = $1;
print «Your IP is: $1\n»;
my $CONFIG, my $BACKUP;
open (CONFIG,$path) or die($!);
open (BACKUP,»>»,$path.»~~») or die($!);
while (){
s{\d+.\d+.\d+.\d+}{$ip};
print BACKUP;
}
close(CONFIG);
close BACKUP;
exec («mv $path~~ $path»);

20 Апрель 2009 г.

Задачка на эзотерическое программирование

Filed under: Perl — Александр Яковлев @ 20:37

Что вернет следующее выражение:
1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9

Большая часть читателей, немного поразмыслив, ответит: 2.
И будет права.
Но весь трюк задачи в том,что правы они будут только наполовину.
Смотрите сами. Вот вывод на perl:

perl -e ‘print 1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9;’
2

Вот вывод на php:

php -r ‘echo 1 ? 2 : 3 ? 4 : 5 ? 6 : 7 ? 8 : 9;’
8

Объясняю, почему так. В большинстве языков (Perl, C, C++, Java, JavaScript, Ruby), эта конструкция читается по такому алгоритму: если верно 1, то выдать 2 – иначе вычислить остальное. В php выражение равносильно

(1 ? 2 : 3 ? 4 : 5 ? 6 : 7) ? 8 : 9

В чем и раскрывается его адская сущность.
Непонятно, почему создатели языка пошли этим странным путём, когда конструкция заимствована из Cи, но сам факт оставляет пищу для размышлений.

Огромное спасибо Shock! за идею.

31 Март 2009 г.

Регэкспы в Perl: секреты

Filed under: Perl — Александр Яковлев @ 20:43

Засел сегодня за perl, причём с твёрдым намерением разобраться в регэкспах.
Пока что сама программа продвигается медленно (хотя уже не выдаёт ошибок деления на 0), но я уже раскопал интересные секреты регэкспов Перла. Коими и спешу поделиться.
Информация редкая, такое не в каждом учебнике найдёшь.

Конструкция Значение
/x Инструкция в конце regexp’а разрешает использование разнообразных пробелов,а также комментов. ОЧЕНЬ РЕКОМЕНДУЮ к использованию: читабельность регэкспа повышается в разы, когда вы разбираете его по кусочкам.Естественно,что пробелы и «диезы» с использованием этого указания надо отделять слешем, если вы хотите их использовать по прямому назначению.
/m Рассматривать переменную как многострочную. ^ и $ отвечают не за начало и конец строки,а за начало и конец любой строки параграфа.
/s Рассматривать переменную как однострочную – . будет отвечать даже символу \n,который обычно она игнорирует.
(?#…) Помечает подстроку как коммент, в отличие от обычного #,который помечает весь остаток строки.Работает только при наличии инструкции /x.
?{CODE} Выполнить код внутри регэкспа (!!!). Код не интерполируется.
(*FAIL) Конструкция автоматически заставляет отвергнуть любые совпадения регэкспа.
(*ACCEPT) Обратно: автоматически утверждает совпадение регэкспа, дальше выражение не проверяется.
(*MARK:name) Ставит метку name в строке на текущей позиции
(*SKIP:name) отменяет все совпадения вплоть до метки name
\K Не учитывать текст,совпавший до этого,в результате регэкспа.

Многие из этого были введены именно в 5.10, поэтому не указаны даже в perlre.
Удачи в использовании!

Powered by WordPress