Regex для захвата имен переменных в выражении? - PullRequest
1 голос
/ 15 января 2020

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

Выражения будут простыми именами переменных, числами или арифметическими c операторами для захвата выражений типа "(недели *) 2) + (3 * days) "* ​​1003 *

Я планирую сначала преобразовать все имена переменных в строке в числа, а затем использовать оконную функцию для вычисления выражения Numberri c.

Для этого мне нужно вытащить все имена переменных и заменить их числами.

Попытка написать регулярное выражение, которое извлекает имена переменных, которые я придумала:

 (?:\s\/+\-\*\()?([A-Za-z_]+[A-Za-z_0-9]*)(?:\s\+\-\/\*\))?

который ищет строки с именами переменных, окруженные арифметическими c операторами, паренами или пробелами, но избегает захвата любых вызовов функций.

Однако, когда я запускаю эту тестовую строку в regextester.com

  a+3+cats+dogs(32)*(cats+dogs)+ x[horse_3]  

, я получаю такой результат:

this result

, что является прогрессом, но я не понимаю, почему «собаки» в dogs(32) захватываются, поскольку за «собаками» не следует оператор, пробел или близкий друг, и почему horse_3 и x захвачены, так как они тоже не подходят? (скобка не указана как разрешенный символ для следования или предшествования ..]

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

1 Ответ

0 голосов
/ 15 января 2020

Есть несколько проблем с вашим регулярным выражением. Во-первых, ваши группы без захвата ищут следующую последовательность символов:

<space>/+-*(

() вместо ( в конечной группе), где вы должны использовать класс символов, чтобы соответствовать только одному из них:

[\s/+*(-]

Во-вторых, вы делаете необязательными все символы-разделители (? после групп без захвата), чтобы они вообще не ограничивали совпадение. Вот почему вы сопоставляете dogs в dogs(32) и x[horse_3].

Наконец, поскольку вы используете группы без захвата, вы не сможете захватить последовательные переменные, например cats+dogs, потому что совпадение на cats будет поглощать + до dogs, предотвращая совпадение.

Я думаю, что это регулярное выражение должно делать то, что вы хотите. Он использует соответствующие классы символов и использует позитивный взгляд вместо второй не захватывающей группы. Чтобы разрешить сопоставление в начале и конце строки, добавляются ^ и $ в качестве чередований в группе без захвата и в заголовке:

(?:^|[\s/+*(-])([A-Za-z_]+[A-Za-z_0-9]*)(?=[\s+/*)-]|$)

Демонстрация на regex101

In JS

let str = 'a+3+cats+dogs(32)*(cats+dogs)+ x[horse_3]+z';
let r = /(?:^|[\s/+*(-])([A-Za-z_]+[A-Za-z_0-9]*)(?=[\s+/*)-]|$)/g;
while (m = r.exec(str)) {
  console.log(m[1]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...