Javascript RegEx Ленивый матч - PullRequest
1 голос
/ 03 мая 2019

Я пытаюсь найти шаблон петли в коде javascript и заменить синтаксис (с: на in), используя приведенный ниже метод регулярных выражений,

var str="for(var x in []) for(var y in [])";

str.replace( new RegExp( '(for\\s*\\(.+\\s+):(\\s+.+\\))', 'ig' ), "\$1in\$2" )

т.е.

for(var x : list)
{
 // something
}

на

for(var x in list)
{
 // something
}

Однако я сталкиваюсь с проблемами, когда в одной строке несколько циклов for.

for(var x : list) { for(var y : list) {
     // something
 }
}

, который является допустимым синтаксисом, однако из-за подхода регулярного выражения Greedy он преобразуется следующим образом:

for(var x : list) { for(var y in list) {
         // something
 }
}

Я пытался изучить синтаксис lazy regex, но не смог заставить его работать.Как мне этого добиться?

Ответы [ 3 ]

1 голос
/ 03 мая 2019

Вы можете добавить ленивые квантификаторы ко всем * и +. и возьмите for как часть замены из-за совпадения.

var str = "for(var x : []) for(var y : [])";

console.log(str.replace(/for\s*?(\(.+?\s+?):(\s+?.+?\))/ig, "for $1in$2"));

Немного короче и включает в себя for в первой группе.

var str = "for(var x : []) for(var y : [])";

console.log(str.replace(/(for\s*?\(.+?):(.+?\))/ig, "$1in$2"));
1 голос
/ 03 мая 2019

Вместо использования ленивых квантификаторов, вы можете использовать отрицательный набор символов, так как они работают лучше, и вы можете использовать это регулярное выражение

(for\s*\([^:]+):([^)]+\))

и заменить его на

$1 in $2

Такжевам не нужно использовать .+\\s+, так как это избыточно, и вместо этого вы можете просто написать .+?, а еще лучше использовать отрицательный набор символов, чтобы он работал быстрее, и аналогично после : вы можете написать \\s+.+ как.+? но опять-таки отрицательный класс символов - лучший выбор, как я упоминал в своем ответе.

Еще один момент, который может привести вас к проблемам, заключается в том, что вы не должны использовать этот \$1in\$2 для замены, а вместо этого использовать $1 in $2 во-первых, вам не нужно экранировать $ как \$, а во-вторых, потому что если ваш цикл for подобен этому, for(var x:list) т.е. без пробела между двоеточием и окружающими переменными, то результат замены, который вы можете получить, будетfor(var xinlist), что сделало бы его недействительным.Вот почему я предложил выше в своем ответе заменить на $1 in $2, чтобы in имел пробел с обеих сторон.

Regex Demo

JS коды,

const s = `for(var x : list)
{
 // something
}

for(var x : list) { for(var y : list) {
     // something
 }
}`

console.log(s.replace(/(for\s*\([^:]+):([^)]+\))/g, '$1 in $2'))
0 голосов
/ 03 мая 2019

Ленивое поведение может быть достигнуто с помощью ? после квантификатора.

const str = "for(var x : list) { for(var y : list) {"
str.replace( new RegExp( '(for\\s*?\\(.+?\\s+?):(\\s+.+\\))', 'ig' ), "\$1in\$2" )

btw.Литералы JavaScript RegEx намного легче читать:

str.replace( /(for\s*?\(.+?\s+?):(\s+.+\))/ig, "\$1in\$2" )
...