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

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 regex он конвертируется следующим образом:

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

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

1
Pratik 3 Май 2019 в 11:01

3 ответа

Лучший ответ

Вы можете добавить ленивые квантификаторы ко всем * и +. и возьмите 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
Nina Scholz 3 Май 2019 в 08:37

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

(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

Коды 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'))
1
Pushpesh Kumar Rajwanshi 3 Май 2019 в 09:20

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

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

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

str.replace( /(for\s*?\(.+?\s+?):(\s+.+\))/ig, "\$1in\$2" )
0
htho 3 Май 2019 в 08:15