LINUX.ORG.RU

Криво обрабатывается простая регулярка в JavaScript


0

1

Вот простой пример:

text="<span class="bold js-clone-url-permission">Read+Write</span> access";
searchPattern="(.*)";
replacePattern="До $1 После";
      
result=text.replace(new RegExp(searchPattern,'g'), replacePattern);

Результат:

До <span class="bold js-clone-url-permission">Read+Write</span> access ПослеДо  После

Вопрос: Почему До После попадает в результат дважды?

Проверено на Firefox 14, Opera 12.

★★★★★
Ответ на: комментарий от note173

С (.+) отрабатывает правильно.

Но таки (.*) - это одно вхождение, на то и скобки.

Чего это яваскрипт лепит еще одну строку справа?

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

Все я спать, задрали меня регулярки. То одно не работает, то другое глючит.

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

Вот что меня смешит в луноходах, так это то что вместо понимания как оно работает, люди тупо перебирают варианты «а что будет если?».

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

Ой, нуб меня затроллировал! Иди читай референс по жабаскрипту (да и PCRE вообще), особенно про модификатор 'g'.

GateKeeper ★★
()

Проблема в g шаблон захватывает всю строку - это первая часть а потом ещё обрабатывает конец строки ($) - это вторая пустая часть

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

Проблема в g шаблон захватывает всю строку - это первая часть а потом ещё обрабатывает конец строки ($) - это вторая пустая часть

Ну так в шаблоне же нету $ чтоб конец строки захватывать.

Я конечно могу воспользоваться (.+), оно эту вашу виртуальную вторую пустую часть не захватит. Я другого не могу понять - с какого перепугу конец строки стал отдельной «частью», чтобы ее обрабатывать? Что вообще подразумевается под понятием «конец строки»? Символов перевода строки/возврата каретки в исходной строке нет. Неужели символ завершения строки (типа нуль?) образует «вторую пустую чать строки»? И вообще символ завершения строки к строке никакого отношения к строке иметь не должен. Ведь, образно говоря, существуют строки без символа конца строки, когда хранится её длина.

Повторю вопрос: откуда берется «вторая пустая часть» в строке? Где она находится? После последнего символа чтоли? А почему не перед первым, если на то пошло?

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

Смотри — сначала lastIndex (положение матчера в строке) регулярного выражения равен 0. Дальше replace матчит паттерн со строкой text целиком — длиной, скажем (лень считать), в 100 символов. Это первое совпадение. Теперь lastIndex равен 100 и совпадает с длиной строки. lastIndex может совпадать с длиной строки (чтобы .* соответствовал пустой строке, например), но не может быть больше ее. Теперь паттерн .* соответствует пустой строке на конце text — у нас есть второе совпадение. Увидев, что lastIndex не изменился (т.к. размер совпадения = 0), replace самостоятельно увеличивает его на единицу (в противном случае метод бы сваливался в бесконечный цикл). Теперь lastIndex > длины строки и процесс замены завершается.

А почему не перед первым, если на то пошло?

Потому что .* — жадный паттерн, он сразу пытается захватить настолько много символов, насколько возможно. Если же использовать ленивый паттерн .*?, то match найдет по одному пустому совпадению в каждом символе строки и одно — в конце строки.

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

От спасибо, хорошо объяснил. Правда, считаю что имхо это неправильное поведение с точки зрения человеческой логики. Паттерн (.*) должен находить вся строку и ничего более!

Кстате, у меня подозрение, что у тебя есть какая-то книга по регуляркам, которой нет у меня, либо ты заморачивался с реализацией вычислений регулярных выражений.

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