Forum Webscript.Ru

Программирование => Регулярные выражения => Тема начата: Vladn от 23 Января 2004, 18:28:09

Название: Все, кроме выражения
Отправлено: Vladn от 23 Января 2004, 18:28:09
Как сказать регулярному выражению фразу "Любая последовательность символов, в которой нет указанной последовательности"? Я знаю как сказать "Любая последовательность символов, в которой нет указанных символов" с помощью [^abcd].
Пример.
Пусть есть строчка
111111

111111111

111111111111

111111111
нужно получить
111111

222222222

111111111111

111111111

если сказать while ($a=~s/

(.*?)1(.*?)<\\/p>/

$1$d$2<\\/p>/) {}; (где $d=2) то получим следующее:
111111

222222222

222222222222

111111111

если сказать while ($a=~s/(

[^(<\\/p>)]*?)(1)/$1$d/) {}; то получим слдующее:
111111

222211111

111111111111

111111111
Название: Все, кроме выражения
Отправлено: Horez от 24 Января 2004, 16:20:45
может, стоит таки разбить задачу на две? или с помощью оператора выбора
Название: Все, кроме выражения
Отправлено: metton от 13 Февраля 2004, 01:50:40
2Vladn
Формулируй вопрос точнее. [^abcd] вовсе не Любая последовательность символов, в которой нет указанных символов", а ЛЮБОЙ (КРОМЕ УКАЗАННЫХ) ОДИН СИМВОЛ. И так как ты это так определил, тем более не ясно что ты хочешь сказать этим: "Любая последовательность символов, в которой нет указанной последовательности". Эта формулировка скорее соответствует:
if(-1 == index($YourStr, $StringThatMustNotBeInYourStr)) {
# $YourStr соответствует критерию "Любая последовательность
# символов, в которой нет указанной последовательности"
}
Название: Все, кроме выражения
Отправлено: Vladn от 13 Февраля 2004, 23:33:37
metton
Читай внимательнее:
Цитировать
Я знаю как сказать "Любая последовательность символов, в которой нет указанных символов" с помощью [^abcd].


И мне нужно не просто определить, есть ли указанная подпоследовательность в данной строке, а заменить текст между открывающим и закрывающим тегами, причем в этом тексте не должно быть другого закрывающего тега.

Я решил эту задачу, но решил некрасиво. Хотелось бы элегантного решения в одну строчку.
Название: Все, кроме выражения
Отправлено: metton от 14 Февраля 2004, 00:26:22
Цитировать
И мне нужно не просто определить, есть ли указанная подпоследовательность в данной строке ...

Так ты определись, тебе нужно: "Любая последовательность символов, в которой нет указанных символов" или то, что я процитировал

И ещё, объясни мне логику вот этой фразы в общем: "И мне нужно не просто определить, есть ли указанная подпоследовательность в данной строке, а заменить текст между открывающим и закрывающим тегами". В первом предложении фигурирует строка и последовательность, которую нужно (или не нужно?! я уже запутался) найти в первой, а во втором предложении - некие тэги.
Я так подозреваю, при написании сообщения ты руководствовался правилом "2 пишем, 1 в уме" :rollingeyes:
Название: Все, кроме выражения
Отправлено: Vladn от 14 Февраля 2004, 00:44:28
metton
Предлагаю не вдаваться в область философии, а решить задачу:
Пусть есть строчка
111111

113451111111

111111111111

111111111
нужно получить
111111

223452222222

111111111111

111111111

Вот мое некрасивое решение:
sub change{
 my $i=1;
 my %tag;
 while ($_[0]=~s/(

.*?<\\/p>)/\\x07$i/s) {
  $tag{$i}=$1;
  $tag{$i}=~s/1/2/g;
  $i++;
  }
 while ($i>1) {
  $i--;
  $_[0]=~s/\\x07$i/$tag{$i}/g;
  }
 }


my $a=\'111111

113451111111

111111111111

111111111\';
print $a."\\n";
change($a);
print $a;


Но я думаю, что на перле можно придумать что-нибудь покрасивее.
Или нет?
Название: Все, кроме выражения
Отправлено: metton от 14 Февраля 2004, 02:55:38
Vladn
Вот тебе решение в одну (ну ладно, в три, но их можно написать в одну ;) ) строчку ;)

my $str = "111111

113451111111

111111111111

111111111";
$str =~ s/(

)(.*?)(<\\/p>)/local($1,$2,$3);$1=~s?1?2?g; $1.$2.$3/ge;
print $str;



зы: 2ALL:
Только я не понял, почему при попытке регэкспить (оператором s///) непосредственно $1, $2 и $3, без их локализации, выводится ошибка: "Modification of a read-only value attempted..."
Что-то я не нашёл такого в книгах.

Название: Все, кроме выражения
Отправлено: Vladn от 14 Февраля 2004, 21:15:40
metton
Спасибо за решение, но более правильно будет записать так:
my $str = "111111

113451111111

111111111111

111111111";
$str =~ s/(

)(.*?)(<\\/p>)/local($1,$2,$3);$2=~s?1?2?g; $1.$2.$3/ge;
print $str;

Но и этот скрипт не заработал на моем ActivePerl v5.6.1. Точнее заработал, но заработал неправильно.
А заработал у меня несколько модифицированный скрипт:

my $str = "111111

113451111111

111111111111

111

111

1123412

11";
print $str."\\n";
$str =~ s/(

)(.*?)(<\\/p>)/my ($a,$b,$c)=($1,$2,$3);$b=~s?1?2?g;$a.$b.$c/ge;
print $str;


Но первоначально у меня стояла следующая задача: отобразить текст в как он есть. Проблема возникает тогда, когда есть символы &nbsp; < &amp; и т.п. Они в браузере даже в

Как оказалось, до сих пор встречаются умники, которые заключают JS-скрипты в комментарии (хотя, браузеры, которые не понимают JS можно найти лишь в музее), и если страницу с таким JS-скриптом обработать "казалось бы элементарным решением" и вывести в браузер, то внутри JS-скрипта будет полная ерунда. Поэтому новая задача:

необходимо обработать текст

& &nbsp; &amp; &lt;

& &nbsp; &amp; &lt;

& &nbsp; &amp; &lt;
так, чтобы получился текст&amp; &amp;nbsp; &amp;amp; &amp;lt;

&amp; &amp;nbsp; &amp;amp; &amp;lt;

&amp; &amp;nbsp; &amp;amp; &amp;lt;


Мой некрасивый вариант решения:sub change{
 my $i=1;
 my %tag;
 while ($_[0]=~s/()/\\x07$i/s) {
  $tag{$i}=$1;
  $i++;
  }
 $_[0]=~s/\\&/\\&amp/g;
 while ($i>1) {
  $i--;
  $_[0]=~s/\\x07$i/$tag{$i}/g;
  }
 }

my $str=\'& &nbsp; &amp; &lt;

& &nbsp; &amp; &lt;

& &nbsp; &amp; &lt;\';
change($str);
print $str;


Может, у кого-нибудь получится красивее?
Название: Все, кроме выражения
Отправлено: metton от 14 Февраля 2004, 21:44:42
Vladn
Ну да, с лексическими переменными я тоже делал, но криво это как-то. Стрянно, почему просто $1, $2, $3  не работают в данном случае...
Название: Все, кроме выражения
Отправлено: Vladn от 14 Февраля 2004, 22:17:09
metton
Наверное, потому что они read only. Тем более, ты далее используешь =~s?1?2?g;, что приводит к перезаписи $1 $2 и $3, точнее - записи в них пустых значений.
Название: Все, кроме выражения
Отправлено: metton от 15 Февраля 2004, 14:19:32
Vladn
То что они read-only я понял. Смущает тор, что я не нашёл про это ничего в "Программировании на Perl".

Цитировать
Vladn:
что приводит к перезаписи $1 $2 и $3, точнее - записи в них пустых значений

А вот это вообще не понял. Почему пустых?
Название: Все, кроме выражения
Отправлено: Vladn от 15 Февраля 2004, 22:07:36
metton
Цитировать
А вот это вообще не понял. Почему пустых?

После каждой операции =~s/// или =~/// переменные $1, $2 и т.д. обновляются в соответствии с этой операцией. А т.к. в выражении =~s?1?2? скобок нет, то все эти переменные принимают нулевое значение. По крайней мере это так на моем ActivePerl 5.6.1

Я придумал более красивое решение мою же поставленной задачи:
sub change{
 my $i=1;
 my %coms;
 while ($_[0]=~s/(<\\!--(.*?)-->)/\\x07$i/s) {
  $coms{$i}=$1;
  $i++;
  }
 $_[0]=~s/\\&/\\&amp;/g;
 while ($i>1) {
   $i--;
   $_[0]=~s/\\x07$i/$coms{$i}/;
   }
  }
Т.е. сначала удаляем комментарии, затем заменяем амперсанты, затем восстанавливаем комментарии.
Название: Все, кроме выражения
Отправлено: metton от 15 Февраля 2004, 23:05:01
Vladn
Цитировать
После каждой операции =~s/// или =~/// переменные $1, $2 и т.д. обновляются в соответствии с этой операцией

Да, об этом я что-то не подумал.

Цитировать
более красивое решение

Красивое? Сначала красота решения у тебя отождествлялась с количеством строчек (а именно одной). Я такое и написал ;)

[OFF]зы: берегись Yukko ;) :D[/OFF]
Название: Все, кроме выражения
Отправлено: Vladn от 16 Февраля 2004, 07:17:20
Цитировать
Красивое?

Читай внимательнее: более красивое
Объясняю для программистов:
var [Красивое] = 1 строчка;
var [Более красивое] = меньше строчек OR более эффективное, чем менее красивое;


Вообще-то я немного тормознул: два раза написал одно и то же решение. Просто я думал, что первое решение было другим.