catastrophi c backstring в регулярном выражении - PullRequest
0 голосов
/ 27 мая 2020

Я использую ниже регулярное выражение

[^\/]*([A-Za-z]+_([A-Za-z]+|-?[A-Z0-9]+(\.[A_Z0-9]+)?|(?:_|:|:-|-[a-zA-Z]+|\.[a-zA-Z]+|[A-Z0-9a-z]+|=|\s|\?|\%|\.|!|#|\*)?)+(?=(,|\/)))+|,[^\/]*

, и оно показывает мне catastrophi c backstring, когда я пытаюсь сопоставить с входной строкой.

/w_100/h_500/e_saturation:50,e_tint:red:blue/c_crop,a_100,l_text:Neucha_26_bold:Loremipsum./l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc/1488800313_DSC_0334__3_.JPG_mweubp.jpg

Ожидаемый выходной массив соответствующего регулярного выражения будет выглядеть как

[ 'w_100',
  'h_500',
  'e_saturation:50,e_tint:red:blue',
  'c_crop,a_100,l_text:Neucha_26_bold:Loremipsum.',
  'l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc' ]

не хочу учитывать имя изображения 1488800313_DSC_0334__3_.JPG_mweubp.jpg в совпадении. следующий

есть ли какой-либо способ решить эту проблему в регулярном выражении или предложить мне хорошее регулярное выражение для моей входной строки.

Ответы [ 2 ]

5 голосов
/ 27 мая 2020

Проблема

Вы используете много вариантов, когда класс персонажа будет более эффективным. Кроме того, вы получаете катастрофический c откат из-за следующего квантификатора:

[^\/]*([A-Za-z]+_([A-Za-z]+|-?[A-Z0-9]+(\.[A_Z0-9]+)?|(?:_|:|:-|-[a-zA-Z]+|\.[a-zA-Z]+|[A-Z0-9a-z]+|=|\s|\?|\%|\.|!|#|\*)?)+(?=(,|\/)))+|,[^\/]*
                                                                                                                           ^

Он пытается сопоставить любое из ваших чередований, но продолжает возвращаться и никогда не проходит через все ваши чередования ( иногда это сравнимо с бесконечным l oop). В вашем случае ваше регулярное выражение настолько неэффективно, что оно истекает. Я удалил половину вашего шаблона, и требуется полсекунды для выполнения почти 200 000 шагов (и это только половина вашего шаблона).


Исходный ответ

Как это можно исправить?

Первый шаг - исправить квантификатор и предотвратить его постоянный возврат. На самом деле это довольно просто, просто сделайте это притяжательным : + станет ++. Изменение квантификатора на притяжательный дает паттерн, выполнение которого занимает около 56 мсек и приблизительно 9К шагов (на моем компьютере)

Второй шаг - повысить эффективность паттерна. Измените свои варианты классов символов, где это возможно.

(?:_|:|:-|-[a-zA-Z]+|\.[a-zA-Z]+|[A-Z0-9a-z]+|=|\s|\?|\%|\.|!|#|\*)?
# should instead be
(?::-|[_:-=\s?%.!#*]|[-.][a-zA-Z]+|[A-Z0-9a-z]+)?

Он намного короче, более лаконичен и менее подвержен ошибкам.

Новый шаблон

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

Этот шаблон занимает всего 271 шаг и менее одной миллисекунды для завершения (да, с использованием механизма PCRE, работает и в Java)

(?<=[,\/])[A-Za-z]+_(?:[A-Z0-9a-z]+|-?[A-Z0-9]+(?:\.[A-Z0-9]+)?|:-|[_:-=\s?%.!#*]|[-.][a-zA-Z]+)++

I также изменил ваш положительный просмотр вперед на положительный просмотр назад (?<=[,\/]) для повышения производительности.


Кроме того, если вам не нужны все указанные c logi c, вы можете просто использовать следующее регулярное выражение (чуть меньше половины шагов, чем мое регулярное выражение выше):

См. используемое здесь регулярное выражение

(?<=[,\/])[A-Za-z]+_[^,\/]+

Результаты

Это результаты в следующем массиве:

PS Я предполагаю, что в вашем ожидаемом результате есть опечатка и что / между l_text и l_fetch также следует разделить; нуждается в пояснении.

w_100
h_500
e_saturation:50
e_tint:red:blue
c_crop
a_100
l_text:Neucha_26_bold:Loremipsum.
l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc

Edit # 1

OP разъяснил ожидаемые результаты. Я добавил , к классу символов в четвертом варианте группы без захвата:

См. Здесь используемое регулярное выражение

(?<=[,\/])[A-Za-z]+_(?:[A-Z0-9a-z]+|-?[A-Z0-9]+(?:\.[A-Z0-9]+)?|:-|[_:-=\s?%.!#*,]|[-.][a-zA-Z]+)++

И в сокращенном виде форма:

См. здесь используемое регулярное выражение

(?<=\/)[A-Za-z]+_[^\/]+

Результаты

В результате получается следующий массив:

w_100
h_500
e_saturation:50,e_tint:red:blue
c_crop,a_100,l_text:Neucha_26_bold:Loremipsum.
l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc

Edit # 2

OP представил другой ввод и выявил проблемы с Edit # 1, связанные с этим вводом. Я добавил logi c, чтобы принудительно выполнить сбой последнего элемента в строке.

Новая тестовая строка:

/w_100/h_500/e_saturation:50,e_tint:red:blue/c_crop,a_100,l_text:Neucha_26_bold:Loremipsum./l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc/sample_url_image.jpg

См. Здесь используемое регулярное выражение

(?<=\/)(?![A-Za-z]+_[^\/]+$)[A-Za-z]+_[^\/]+

Те же результаты, что и в Edit # 1.


Версия PCRE (если кто-то ее ищет) - более эффективен, чем метод выше:

См. Регулярное выражение здесь используется введите здесь описание ссылки

(?<=\/)[A-Za-z]+_[^\/]+(?:$(*SKIP)(*FAIL))?
0 голосов
/ 28 мая 2020

Предположим, что в вашем примере есть опечатка, например, последний / также будет разделен:

Вы можете просто разделить на /, а затем отфильтровать элементы .jpg:

function splitWithFilter(line, filter) {
    var filterRe = filter ? new RegExp(filter, 'i') : null;
    return line
    .replace(/^\//, '') // remove leading /
    .split(/\//)
    //.filter(Boolean)    // filter out empty items (alternative to above replace())
    .filter(function(item) {
        return !filterRe || !item.match(filterRe);
    });
}

var str = "/w_100/h_500/e_saturation:50,e_tint:red:blue/c_crop,a_100,l_text:Neucha_26_bold:Loremipsum./l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc/1488800313_DSC_0334__3_.JPG_mweubp.jpg";
console.log(JSON.stringify(splitWithFilter(str, '\\.jpg$'), null, ' '));

Ожидаемый результат:

[
 "w_100",
 "h_500",
 "e_saturation:50,e_tint:red:blue",
 "c_crop,a_100,l_text:Neucha_26_bold:Loremipsum.",
 "l_fetch:aHR0cDovL2Nsb3VkaW5hcnkuY29tL2ltYWdlcy9vbGRfbG9nby5wbmc"
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...