Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Замена первых символов строки, одной регуляркой 
:(
    Опции темы
amg
Дата 27.4.2007, 16:01 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



На одном из форумов наткнулся на такую задачку:

есть строка, допустим
$s = '    2   3  4    5 6 78 9';
Нужно получить
$s = 'nbsp;nbsp;nbsp;nbsp;2   3  4    5 6 78 9';

Поначалу показалось, что это очень легко. Но не тут то было!
Конечно, решается с использованием цикла либо 
Код

$s =~ s/^(\s+)/'nbsp;' x length($1)/e;

А вот можно ли сделать это просто одним регулярным выражением, без циклов и опции /e?
PM MAIL   Вверх
nitr
Дата 27.4.2007, 21:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



думаю нет. "регулярка" не повторяет поиск/замену с начала текста/строки... (если есть повтор - тогда да, не нашел повтор... надо маны подымать smile) ) на что и нужен цикл или твоя конструкция...

Добавлено через 12 минут и 20 секунд
даже с заглядыванием назад не выйдет... не знаю (плохо читал теорию ;) ), но я так понял: в памяти исходная, по которой меняет, и получаемая..., т.е. если бы было иначе, то можно было примерно так /(^\s|(?<=;)\s)//


--------------------
PM   Вверх
Nab
Дата 27.4.2007, 22:20 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Интересная задачка однако smile
и вот верное решение smile
Код

$s =~ s/\G(?:nbsp;)*\s/nbsp;/g;


объяснить не смогу, сам понимаю подсознанием, дошел методом научного тыка smile


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
nitr
Дата 27.4.2007, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Nab, ну вот так и знал =))) 
Цитата(nitr @  27.4.2007,  21:46 Найти цитируемый пост)
плохо читал теорию ;)

\G всему решение =)

Добавлено через 7 минут и 45 секунд
но честно, и такое работает smile))
Код

$s =~ s/\G\s/nbsp;/g;


Добавлено через 9 минут и 47 секунд
Цитата(perldoc perlre)

    \G  Match only at pos() (e.g. at the end-of-match position
        of prior m//g)

A word boundary (\b) is a spot between two characters that has a \w on one side of it and a \W on the other side of it (in either order), counting the imaginary characters off the beginning and end of the string as matching a \W. (Within character classes \b represents backspace rather than a word boundary, just as it normally does in any double-quoted string.) The \A and \Z are just like ``^'' and ``$'', except that they won't match multiple times when the /m modifier is used, while ``^'' and ``$'' will match at every internal line boundary. To match the actual end of the string and not ignore an optional trailing newline, use \z.

The \G assertion can be used to chain global matches (using m//g), as described in Regexp Quote-Like Operators in the perlop manpage. It is also useful when writing lex-like scanners, when you have several patterns that you want to match against consequent substrings of your string, see the previous reference. The actual location where \G will match can also be influenced by using pos() as an lvalue: see pos in the perlfunc manpage. Currently \G is only fully supported when anchored to the start of the pattern; while it is permitted to use it elsewhere, as in /(?<=\G..)./g, some such uses (/.\G/g, for example) currently cause problems, and it is recommended that you avoid such usage for now.



--------------------
PM   Вверх
Nab
Дата 27.4.2007, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Хитрый ты однако... а теперь попытайся объяснить народу, почему оно работает....
На пальцах, чтоб все поняли smile


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
arto
Дата 28.4.2007, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



\G сохраняет позицию предидущего совпадения.
PM MAIL ICQ   Вверх
Nab
Дата 28.4.2007, 01:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Цитата(arto @  28.4.2007,  00:53 Найти цитируемый пост)
\G сохраняет позицию предидущего совпадения.

Дык понятно smile Или думаешь я от фонаря решение взял?
А как оно в конкретном случае то работает?
Распиши плиз...
Я тяжело пришел к этому варианту, у меня раньше никогда с \G не получалось... теперь я знаю что не правильно понимал его работу, но при этом ясности в этом вопросе у меня все одно нет... :(
Кто бы разжевал поподробнее.... smile


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
amg
Дата 28.4.2007, 07:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Господа! Снимаю шляпу!

Про \G я тоже думал, приходилось сталкиваться (нужно было по образцу сделать регулярное выражение для похожих на образец строк), но почему то считал, что \G можно использовать только внутри цикла.

Еще я рад, что интуиция меня не обманула: задача действительно имеет решение.
PM MAIL   Вверх
korob2001
Дата 1.5.2007, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Я так понимаю принцип работы такой регулярки:
Код

#!/usr/bin/perl -w
use strict;

my $s = '    2   3  4    5 6 78 9';
my $count = 0;

$s =~ s/\G(\s)(?{sleep 1 & print "Position: @{[$count++]}\n"})/&nbsp;/g;

print "$s\n";

Утверждение \G запоминает позицию следующую за предидущим найденным соответствием, в нашем случае это 1 пробел. Далее из-за модификатора g циклически идём по строке, символ за символом. Если в сохранённой, утверждением \G, позиции символ совпадает с шаблоном \s значит делаем замену, в противном случае поиск завершается.
Вобщем при поиске каждого последующего символа пробела, мы утверждаем что в следующей позиции будет именно пробел, а не какй-нить другой символ. Если это не так, то поиск завершается, если да, то происходит замена. Именно потому, что мы утверждаем, машина регулярных веражений, завершает свою работу, вместо того, что бы продолжить поиск в следующей позиции, так как установлен модификатор g.

ЗЫ: Это моё мнение, возможно оно и не верное. В книгах и документации как-то мутно описана эта тема.


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
nitr
Дата 1.5.2007, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



korob2001, думаю самое нормальное описание и я тоже с ним соглашусь, даже если перевести из дока, то получим некий "замут", но попрактиковаться и более менее ясно, но согласен, задача была хорошей smile


--------------------
PM   Вверх
Nab
Дата 1.5.2007, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



korob2001, да неплохо сказал smile но я не соглашусь с некоторыми определениями... Утверждение \G боюсь запоминает не позицию за или перед, а это как \b граница между словами, так и \G граница между предыдущим найденным соответствием, и остальным образцом... Хотя ей и соответствует числовой идентификатор, который указывает на позицию последнего символа последнего найденного соответствия...
Посмотреть его можно функцией pos, и даже изменить можно, чтобы поиск продолжался с другой позиции...

Так что не все так просто, как хотелось бы smile



--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
korob2001
Дата 1.5.2007, 23:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2871
Регистрация: 29.12.2002

Репутация: 31
Всего: 61



Цитата(Nab @  1.5.2007,  18:10 Найти цитируемый пост)
korob2001, да неплохо сказал  но я не соглашусь с некоторыми определениями... Утверждение \G боюсь запоминает не позицию за или перед, а это как \b граница между словами, так и \G граница между предыдущим найденным соответствием, и остальным образцом... Хотя ей и соответствует числовой идентификатор, который указывает на позицию последнего символа последнего найденного соответствия...
Посмотреть его можно функцией pos, и даже изменить можно, чтобы поиск продолжался с другой позиции...

Так что не все так просто, как хотелось бы 


Привожу цитату из книги "Программирование на Perl" авторов перечислять не буду и так все поняли о какой книге идёт речь. Стр. 224 (последний абзац).
Цитата

Утверждение \G представляет в шаблоне ту же точку, которую pos представляет вне его. Если мы осуществляем последовательный поиск в строке с модификатором /g (или воспользовавшись функцией pos для непосредственного вызова начальной точки), то можем использовать \G для задания позиции сразу за предидущим найденным соответствием. Т.е. он соответствует месту непосредственно перед тем символом, текущая позиция которого будет определена посредством pos.

Короче позиция которая находится, непосредственно за последним найденым соответствием. Т.е. следующим будет найден тот символ который следует за предидущим. Позиция же указывается непосредственно между пред идущим и следующим символом.

Добавлено через 6 минут и 46 секунд
А вопрос был действительно очень интересный.


--------------------
"Время проходит", - привыкли говорить вы по неверному пониманию. 
"Время стоит - проходите вы".
PM MAIL WWW ICQ MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0952 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.