проPerl (изучая регулярные выражения...)

Модератор: Модераторы разделов

Аватара пользователя
greengroon
Сообщения: 119
ОС: Ubuntu 9.04, FreeBSD 7.2

проPerl

Сообщение greengroon »

Как-то я уже спрашивал как перевести слова в текстовом файле в нижний регистр, но к сожалению не нашел свой топик (в поиске доступны только 10 последних). Поэтому извиняюсь, если опять...
Когда мне подкинули скрипт на Perl, который это делал, я решил осваивать понемногу этот ацкий язык. Вопрос следующий. Почему этот скрипт на консоль выводит слово ВАСЯ, если я от него ожидаю слово вася?

Код: Выделить всё

#! /usr/bin/perl -w
use diagnostics;
$str="ВАСЯ";
$str=lc$str;
print "$str\n";


спустя пару минут...

Если ВАСЯ набираю как WASYA то все работает. Как русский язык заставить?
Какая GNUсная, GNUсная жизнь...
Спасибо сказали:
Аватара пользователя
fbi
Сообщения: 34

Re: проPerl

Сообщение fbi »

добавте use locale

Код: Выделить всё

#! /usr/bin/perl -w
use diagnostics;
use locale;
$str="ВАСЯ";
$str=lc$str;
print "$str\n"
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: проPerl

Сообщение allez »

greengroon
Встречный вопрос номер раз: а почему вы пытаетесь заставить скрипт обработать строку на не понятном ему языке? Если использовать латиницу, то все работает:

...

$ cat script.pl #!/usr/bin/perl -w use diagnostics; $str = "VASYA"; $str = lc $str; print "$str\n"; $ ./script.pl vasya

И встречный вопрос номер два: почему вы не хотите читать документацию? Вот выдержка из perldoc perlfunc:
lc EXPR
lc Returns a lowercased version of EXPR. This is the internal function implementing the "\L" escape in
double‐quoted strings. Respects current LC_CTYPE locale if "use locale" in force. See perllocale
and perlunicode for more details about locale and Unicode support.

If EXPR is omitted, uses $_.


В общем, читайте perldoc perllocale и perldoc perlunicode. Если после прочтения, усвоения и апробирования полученных знаний на практике проблемы и вопросы не исчезнут, пишите.
Спасибо сказали:
Аватара пользователя
greengroon
Сообщения: 119
ОС: Ubuntu 9.04, FreeBSD 7.2

Re: проPerl

Сообщение greengroon »

Использование прагмы use locale результата не дало. После беглого просмотра perldoc perlunicode (у меня локаль utf-8), написал use utf-8. После этого большой ВАСЯ стал маленьким вася, правда, при этом перл вывел на кансоль

Код: Выделить всё

 Wide character in print at hello1.pl line 6 (#1)
    (W utf8) Perl met a wide character (>255) when it wasn't expecting
    one.  This warning is by default on for I/O (like print).  The easiest
    way to quiet this warning is simply to add the :utf8 layer to the
    output, e.g. binmode STDOUT, ':utf8'.  Another way to turn off the
    warning is to add no warnings 'utf8'; but that is often closer to
    cheating.  In general, you are supposed to explicitly mark the
    filehandle with an encoding, see open and perlfunc/binmode.

Окончательный вариант прагмы стал use encoding utf-8.
Какая GNUсная, GNUсная жизнь...
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: проPerl

Сообщение allez »

Окончательный вариант прагмы стал use encoding utf-8.
Что же, можно и так, а можно еще использовать binmode STDOUT, ':utf8';:

...

$ cat script.pl #!/usr/bin/perl -w use diagnostics; use locale; use utf8; binmode STDOUT, ':utf8'; $str = "ВАСЯ"; $str = lc $str; print "$str\n"; $ ./script.pl вася


Но use encoding utf-8, конечно, покороче будет. :)
Спасибо сказали:
Аватара пользователя
greengroon
Сообщения: 119
ОС: Ubuntu 9.04, FreeBSD 7.2

Re: проPerl

Сообщение greengroon »

Это еще не все. Все это я неспроста тут спрашивал ). Я захотел разобраться в этой записи, любезно мне предоставленной однажды одним пользователем форума (явно мастер перла)).

Код: Выделить всё


cat file | perl -p -e 'use encoding "utf8";s/(.)(.*?)\s+(.)(.*?)$/uc($1).lc($2)." ".uc($3).lc($4)/ge' > file1.txt

У меня был файл file. А в нем списки имен и фамилий, набранных в верхнем регистре. (типа ВАСЯ ВАСЬКИН) Нужно было переформатировать их в нижний регистр и при этом оставить первую букву заглавной. Команда, которая выше с этим справилась. Но я подумал, что может можно проще написать, например используя функции lc и ucfirst. Пока не получается. Подскажите, почему. Вот мой вариант.

Код: Выделить всё

cat /home/evgeny/MyPerlScripts/file | perl -p -e 'use encoding "utf-8"; s/(\w+)/lc ucfirst;' > file1.txt

Это я типа хочу заменить все слова в файле (\w+) на нижний регистр а потом первую букву на верхний, но чего то не получается - выдает Substitution replacement not terminated at -e line 1.
Какая GNUсная, GNUсная жизнь...
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: проPerl

Сообщение allez »

Вы не поставили символ "/" после "ucfirst" и тем самым не завершили оператор подстановки s///.
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: проPerl

Сообщение pcodr »

Вот вам еще пару вариантов.
1) Похож на тот, что уже выше писали, но без лишних uc

Код: Выделить всё

cat test.txt | perl -M'encoding utf8' -p -e 's/(.)(.+?)\s+(.)(.+)/$1.lc($2)." ".$3.lc($4)/e'

2) map рулит, скобки придумали трусы :)

Код: Выделить всё

cat test.txt | perl -M'encoding utf8' -p -e '$_ = join " ", map ucfirst, split/\s+/, lc, 2'
remote system type is unix
Спасибо сказали:
Аватара пользователя
greengroon
Сообщения: 119
ОС: Ubuntu 9.04, FreeBSD 7.2

Re: проPerl

Сообщение greengroon »

Да, уж... Пойду дальше читать, надеюсь я еще не совсем безнадежен.


Объясните пожалуйста, почему file1 получается пустым, если команда выглядит так

host@user

cat /file | perl -w -e -p 'use encoding "utf-8"; s/\s+(\w)\s+/lc$1/;' > file1 Use of uninitialized value $_ in -p at -e line 1.

У меня тут так
найти любые слова \w+
перед которыми или после которых есть пробел или пробелы \s+
заменить найденые слова на то же самое только в нижнем регистре lc$1
поиск и замена происходит глобально (многократно) g
Какая GNUсная, GNUсная жизнь...
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: проPerl

Сообщение diesel »

perl -w -p -e 'command'

в любом случае, перловое выражение должно следовать за -e.
Спасибо сказали:
Аватара пользователя
csx
Сообщения: 302
Статус: Сыч Домовый
ОС: Что сломалось, то и чиним...

Re: проPerl

Сообщение csx »

Пробелы кстати, канут в лету при таком раскладе..

Кстати, если не читал http://minimalperl.com/ рекомендую скачать купить и прочесть. Лучшее по перлу для повседневных задач, что я когда-либо встречал.
-- Как называется болезнь когда всё время по телефону разговариваешь?
-- Техподдержка...
Спасибо сказали:
Аватара пользователя
greengroon
Сообщения: 119
ОС: Ubuntu 9.04, FreeBSD 7.2

Re: проPerl

Сообщение greengroon »

perl -w -p -e 'command'
в любом случае, перловое выражение должно следовать за -e.

Спасибо. Честно говоря, не знаю зачем нужна опция -e. Оставил ее еще с вашей команды ;-). Теперь слова выдает, правда все так же, как в file в верхнем регистре.
Кстати, если не читал http://minimalperl.com/ рекомендую скачать купить и прочесть.

Спасибо за книжку. Скачал. Теперь буду читать вместе с начатой Learning Perl by Randal.
Какая GNUсная, GNUсная жизнь...
Спасибо сказали:
Аватара пользователя
greengroon
Сообщения: 119
ОС: Ubuntu 9.04, FreeBSD 7.2

Re: проPerl

Сообщение greengroon »

Не понимаю... Разве lc и \L это не одно и то же? И почему (\w+) лучше, чем \s+\w+\s+?
Какая GNUсная, GNUсная жизнь...
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: проPerl

Сообщение diesel »

greengroon писал(а):
08.08.2009 18:27
perl -w -p -e 'command'
в любом случае, перловое выражение должно следовать за -e.

Спасибо. Честно говоря, не знаю зачем нужна опция -e. Оставил ее еще с вашей команды ;-). Теперь слова выдает, правда все так же, как в file в верхнем регистре.
Кстати, если не читал http://minimalperl.com/ рекомендую скачать купить и прочесть.

Спасибо за книжку. Скачал. Теперь буду читать вместе с начатой Learning Perl by Randal.

Вот пара примеров:

Код: Выделить всё

diesel@debian:~$ echo "ПРИВЕТ МИР "  | LC_CTYPE="en_US.UTF-8" perl -CIOE -n  -e 'print lc $_'
привет мир

diesel@debian:~$ echo "ПРИВЕТ МИР "  |  perl -CIOE   -p  -e 's/(.*?)\s(.*?)/\L$1 \U$2/'
привет МИР


Вот ситуация в которой видно как срабатывает Ваш пример:

Код: Выделить всё

diesel@debian:~$ echo " П РИВЕТ МИР "  | perl -CIOE -w -p -e 's/\s+(\w)\s+/lc$1/;'
lcПРИВЕТ МИР


greengroon писал(а):
08.08.2009 18:42
Не понимаю... Разве lc и \L это не одно и то же?

не совсем. об этом написано в perldoc -f lc.
по поводу CLI-опций perl, стоит прочитать perldoc perlrun
Спасибо сказали:
pcodr
Сообщения: 283
ОС: Debian

Re: проPerl

Сообщение pcodr »

greengroon писал(а):
07.08.2009 16:11
Объясните пожалуйста, почему file1 получается пустым, если команда выглядит так

host@user

cat /file | perl -w -e -p 'use encoding "utf-8"; s/\s+(\w)\s+/lc$1/;' > file1 Use of uninitialized value $_ in -p at -e line 1.


Потому что вероятно должно быть так

Код: Выделить всё

cat test.txt | perl -p -M'encoding utf8' -e 's/(\s+)(\w+)(\s+)/$1.lc($2).$3/ge'


Для того что бы во второй части оператора замены можно было использовать подпрограммы нужно указывать модификатор e.
remote system type is unix
Спасибо сказали:
Аватара пользователя
ZyX
Сообщения: 355
ОС: Gentoo

Re: проPerl

Сообщение ZyX »

pcodr писал(а):
08.08.2009 22:30
Потому что вероятно должно быть так

Код: Выделить всё

cat test.txt | perl -p -M'encoding utf8' -e 's/(\s+)(\w+)(\s+)/$1.lc($2).$3/ge'


Для того что бы во второй части оператора замены можно было использовать подпрограммы нужно указывать модификатор e.

А зачем нам «\s+»? Раз мы не меняем пробелы, то логичнее, во-первых, убрать «+»,
а, во-вторых, использовать конструкции (?<=…) и (?=…):

Код: Выделить всё

cat test.txt | perl -p -M'encoding utf8' -e 's/(?<=\s)(\w+)(?=\s)/lc($1)/ge'
Спасибо сказали: