LINUX.ORG.RU

Помогите написать регулярное выражение.


0

0

Простое-простое. Есть полное имя файла (с путём). Надо в $1 записать всё, что до последней точки, а в $2 - всё что после неё (так сказать расширение). Задача осложняется тем, что этой точки может и не быть :)

PS Написать естественно на perl



Елки-палки, perldoc File::Basename
Там же есть и примеры.
Модуль входит в стандартный дистрибутив Perl.

В твоем случае (untested):
my ($name,$path,$suffix) = fileparse($f, '\..*');
где $f - полный путь.

Onanim
()
Ответ на: комментарий от Onanim

Спасибо тебе, добрый человек :) А я всё старинке, всё сам :)

Eldhenn
() автор топика

> Простое-простое. Есть полное имя файла (с путём). Надо в $1 записать
> всё, что до последней точки, а в $2 - всё что после неё (так сказать
> расширение). Задача осложняется тем, что этой точки может и не быть :)
>
> PS Написать естественно на perl

/(.+)(?:\.(.+))/

int19h ★★★★
()
Ответ на: комментарий от Eldhenn

Ммм... только одна проблема - как бы ему сказать, что directory separator это m{\/\\} ?

Ни фига вопроса на понял. File::Basename будет работать правильно
на любой (поддерживаемой) платформе - Unix, Win32, Mac, VMS.
Он знает, какой правильный directory separator.

Если же тебе надо на Unix обрабатывать имена другой системы (скажем
Win32), то надо использовать fileparse_set_fstype() для явного
указания типа системы, например.

fileparse_set_fstype('MSWin32');
my ($name,$path,$suffix) = fileparse($f, '\..*');
# AFAIK, оба слэша / и \ будут directory separators

BTW, скажи пожалуйста: неужели ты ниасилил это прочитать сам?
Это же в том же perldoc File::Basename написано!

HTH

Onanim
()
Ответ на: комментарий от int19h

2int19h:

Может надо проверять свои решения (или хотя бы писать "untested")

$ perl -w -e '$_="/a/b/c.cpp"; /(.+)(?:\.(.+))/; print "$1\n"'
/a/b/c

Хорошо, работает...

$ perl -w -e '$_="/a/b/c."; /(.+)(?:\.(.+))/; print "$1\n"'
Use of uninitialized value in concatenation (.) or string at -e line 1.

Вроде как жопа...

$ perl -w -e '$_="/a/b/c"; /(.+)(?:\.(.+))/; print "$1\n"'
Use of uninitialized value in concatenation (.) or string at -e line 1.

И еще одна...

Четай доки по regular expressions.

Onanim
()
Ответ на: комментарий от Onanim

Ман как раз кривой. А когда я залез в сам модуль, то увидел, что MSWin32 обрабатывает как прямые, так и обратные слэши. Спасибо огромное за подсказку :)

Eldhenn
() автор топика
Ответ на: комментарий от Eldhenn

> Ман как раз кривой.

Тогда выкинь свой дистрибутив Perl.

perldoc File::Basename на всех доступных мне машинах выдает текст,
совпадающий с этим:
http://search.cpan.org/~nwclark/perl-5.8.7/lib/File/Basename.pm
И где там, мил человек, кривизна?

"...разруха не в клозетах, а в головах..." (C)

Onanim
()
Ответ на: комментарий от Eldhenn

> И где тут возможное отсутствие точки?

Извиняюсь, после последней скобки должен стоять ?, разумеется

int19h ★★★★
()
Ответ на: комментарий от Onanim

> Может надо проверять свои решения (или хотя бы писать "untested")

Надо =/ А точнее, надо внимательней смотреть, когда делаешь Ctrl+Z.

* там вместо плюса во втором случае, разумеется. Позор мне.

int19h ★★★★
()
Ответ на: комментарий от int19h

> Извиняюсь, после последней скобки должен стоять ?, разумеется

Разумеется, это очередная ошибка.

$ perl -w -e '$_="/a/b/c.cpp"; /(.+)(?:\.(.+))?/; print "$1\n"'
/a/b/c.cpp

Теперь суффикс не отделяется вообще.

Может все-таки лучше поучиться и не подавать плохой пример новичкам в Perl?

Onanim
()
Ответ на: комментарий от Onanim

Дистрибутив у меня месяц назад скачанный с perl.com Кривизна... Ну при внимательном прочтнении осталась только одна претензия - неопределённость понятий VMS, MSWin32 и т.д. Что MSWin32 понимает прямые слэши, а VMS это "default to Unix" я узнал только посмотрев в текст модуля.

Eldhenn
() автор топика

Ладно, раз уж тема продолжилась... Можно ли это написать одним выражением? С использованием всех наворотов Perl вроде look-ahead и look-behind? Просто Фридла нет под рукой, чтобы помедитировать...

Eldhenn
() автор топика
Ответ на: комментарий от Eldhenn

2Eldhenn:
> Дистрибутив у меня...

Да ладно, это я так, ворчу по-стариковски...

Onanim
()
Ответ на: комментарий от Eldhenn

> Ладно, раз уж тема продолжилась... Можно ли это написать одним
> выражением?

Можно б/п :-)

> С использованием всех наворотов Perl вроде look-ahead и
> look-behind?

С наворотами может и нельзя, а вот без них - наверное можно :-)))

Уточним условие:
> Надо в $1 записать всё, что до последней точки,
> а в $2 - всё что после неё
>
Уточнение 1 - очевидно, после точки не должно быть слеша.
Уточнение 2 - непонятно, куда включать саму точку, пусть для
определенности она будет частью суффикса:

m!^(.*?)(\.[^/.]*|)$!

Надеюсь не ошибся ;-) Но ты сам видел из этой дискуссии, что нефиг
изобретать велосипед.

HTH

Onanim
()
Ответ на: комментарий от Onanim

> Может все-таки лучше поучиться и не подавать плохой пример новичкам в

Да, мне определенно пора было перечитать внимательно man perlre, и
запомнить-таки разницу между greedy и non-greedy регэкспами. Но
все-таки я его добью.

Пробуем еще раз: /(.+?)(?:\.([^.\/]*))?$/;

Да, ununitialized value в concatenation при отсутствии точки в имени
файла - имхо оно так и должно быть, т.к. пустое расширение (т.е. файл,
оканчивающийся на точку) - это все-таки не то же самое, что его
отсутствие.

int19h ★★★★
()
Ответ на: комментарий от Onanim

Ну точку можно было вообще никуда не включать, про неё всё понятно...

Не понял - что там пайп в конце делает?

Eldhenn
() автор топика
Ответ на: комментарий от Onanim

И я не вижу случая отсутствия точки...

Eldhenn
() автор топика
Ответ на: комментарий от int19h

ак вот как вложенные скобки работают... На всю жизнь запомню :) Правда, я бы сказал /([^\\\/]+?)(?:\.([^.]*))?$/

Eldhenn
() автор топика
Ответ на: комментарий от Eldhenn

> Ну точку можно было вообще никуда не включать, про неё всё понятно...

Если ее включать, то проще получается. Сам сравни мой регэкп и его =)

> Не понял - что там пайп в конце делает?

Это не пайп, а alternation. Как раз отрабатывает случай, когда точки
(и, следовательно, расширения) нет - т.е. match на пустую строку.

int19h ★★★★
()
Ответ на: комментарий от Eldhenn

> Не понял - что там пайп в конце делает?

Где пайп? С шеллом путаешь? Это "ИЛИ".
То есть суффикс - это:
1. или точка и что-то (опционально) после
2. или пустая строка (поэтому после alteration ничего нет).

Идея такова, что при любом раскладе pattern matching будет
успешен и $1 и $2 будут defined (хотя могут быть и пустыми
строками).

Проверим на разных пример, вплоть до пустого имени файла:

$ perl -n -e 'chomp; m!^(.*?)(\.[^/.]*|)$!; print "-$1- -$2-\n"'
/aaa/bbb/ccc/file.cpp
-/aaa/bbb/ccc/file- -.cpp-
/aaa/bbb/ccc/file.
-/aaa/bbb/ccc/file- -.-
/aaa/bbb/ccc/file
-/aaa/bbb/ccc/file- --
file.cpp
-file- -.cpp-
file.
-file- -.-
file
-file- --
.cpp
-- -.cpp-
.
-- -.-

-- --
^D
$

Onanim
()
Ответ на: комментарий от int19h

>> Ну точку можно было вообще никуда не включать, про неё всё понятно.

> Если ее включать, то проще получается. Сам сравни мой регэкп и его

Ну... возможно на сааамую малость проще ;-)
Я ее включал потому, что File::Basename делает аналогично.
Да и вообще - чем эта последняя точка такая особенная, чтобы ее не
включать? В Unix у всех точек равные права :-)))

Onanim
()
Ответ на: комментарий от Onanim

Особенная она тем, что мы точно знаем о её местоположении. То есть известно, что полученные нами 2 части отделяются одним символом, именно - точкой.

Eldhenn
() автор топика
Ответ на: комментарий от Onanim

>Где пайп? С шеллом путаешь? Это "ИЛИ". >То есть суффикс - это: >1. или точка и что-то (опционально) после >2. или пустая строка (поэтому после alteration ничего нет).

So desu ne...

Eldhenn
() автор топика

В общем, большое спасибо всем участникам дискуссии :) Задача решена, удовольствие от дискуссии получено :)

Eldhenn
() автор топика
Ответ на: комментарий от Onanim

> Ну... возможно на сааамую малость проще ;-)
> Я ее включал потому, что File::Basename делает аналогично.
> Да и вообще - чем эта последняя точка такая особенная, чтобы ее не
> включать? В Unix у всех точек равные права :-)))

Ну он задачу поставил так - в $2 все, что _после_ точки =)

Короче, спасибо за тыканье в ошибки. Теперь, надеюсь, запомню. Вообще в
связи с перманентным забыванием о greedyness регэкспов у меня
перманентно возникают затыки - это я один такой тупой, или
действительно есть такая проблема?

int19h ★★★★
()
Ответ на: комментарий от int19h

> Вообще в связи с перманентным забыванием о greedyness регэкспов
> у меня перманентно возникают затыки - это я один такой тупой,
> или действительно есть такая проблема?

Да просто практиковаться чаще надо :-)
Регэкспами надо думать, а это приходит с практикой... и пропадает
без нее. Аналогично любым другим навыкам.

Onanim
()
Ответ на: комментарий от Onanim

Согласен. Я вот с ними не имел дела серьзёно уже года два. Всё нафиг забыл :)

Eldhenn
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.