2013-04-24 4 views
2

Я думал, что это был бы «ежу понятно» дополнение к моему Regex, но я, конечно, было опровергнуто ...Regular Expression кванторов

Мой текущий Regex возвращает истину, если строка является символом (- , $, +, = (,), {,}):

(/^[-$+)(}{]$/).test(token); 

Я хочу добавить два символа в Regex, оператор присваивания (=), а оператор равенства (==). Моя интуиция вела меня сделать что-то вдоль линий, чтобы вернуть истину, если существует маркер с один или два «=»:

(/^[-$+)(}{]|(=){1,2}$/).test(token); 

, но все же, если фактический маркер (/^[-$+)(}{]|(=){1,2}$/).test("===") верно возвращается.

Может кто-то пролить свет на мои недостатки regEx?

Благодаря

ответ

4

Из-за приоритета операторов, то или ветви включают начало (^) и конец ($) нулевой ширины совпадений. Для того, чтобы поймать = или ==, вы должны использовать:

(/^([-$+)(}{]|={1,2})$/).test(token); 
+0

интересно, так что все выражение просто должно было быть заключено в одну группу? – Joey

+0

Да, в противном случае ваши совпадения ('^') и end ('$') нулевой ширины включаются в или ('|'). – Adrian

+0

Полезно знать, спасибо – Joey

4

Используйте это регулярное выражение:

(/^(?:[-$+)(}{]|={1,2})$/).test(token); 

Если вы используете якоря ^ (вход запуска) или $ (конец ввода) перед & после трубы (OR для регулярного выражения) вы должны заключить LHS и RHS в | в скобках, чтобы сгруппировать их так, чтобы ^ или $ применимы для всего регулярного выражения внутри скобок.

+0

Зачем беспокоиться о '?:'? –

+0

О, я совсем не беспокоился :) IMHO '?:' Предназначен для ситуаций, подобных этому, когда есть необходимость в группе, но в то же время нет необходимости захватывать. – anubhava

+0

Я знаю, что он делает. Вопрос в том, почему вы предложили использовать его для проблемы OP? Это усложняет регулярное выражение и, похоже, ничего не спасает. (Поскольку все группы захвата игнорируются, нет необходимости различать группы захвата и группы без захвата.) –

6

Вы столкнулись с тонкой проблемой приоритета оператора.

/^[-$+)(}{]|(=){1,2}$/ 

^ и $ связывают более плотно, чем |, так что это эквивалентно

/(?:^[\-$+)(}{])|(?:={1,2}$)/ 

вместо того, что вы, вероятно, хотите, который должен иметь ^...$ заключите |:

/^(?:[\-$+)(}{]|={1,2})$/ 

или упрощенного

/^(?:[\-$+(){}]|==?)$/ 

/^(?:[\-$+(){}]|==?)$/.test("===") === false; 
/^(?:[\-$+(){}]|==?)$/.test("()") === false; 
/^(?:[\-$+(){}]|==?)$/.test("=") === true; 
/^(?:[\-$+(){}]|==?)$/.test("==") === true; 
/^(?:[\-$+(){}]|==?)$/.test("(") === true; 

Отступление о захвате против не-сохраняющих круглых скобок

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

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

  1. изменения нумерации существующих групп, так как JS не назвали группы,
  2. с помощью оператора с более эффекты, чем мне нужно могу запутать сопровождающую в мышление я захватывая содержание по причине,
  3. изменения поведения отдаленного exec цикла, (Это в основном проблема с perlish глобальных матчей как @foo = $str =~ /(foo(bar))/g , но каждая один раз в некоторое время вы увидите JS код делает что-то подобное)
  4. изменения поведения (функции возможно VARIADIC) заменителя определена в другом месте, как
     
    newStr = oldStr.replace(
        regexDefinedEarlier, 
        function (var_args) { 
         return [].slice.call(arguments, 1, arguments.length - 2).join(''); 
        }); 
    
+0

Зачем беспокоиться с '?:'? –

+0

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

+0

@TedHopp и Joey, пожалуйста, см. Отступление, которое я добавил к моему ответу. Короче говоря, я использую '(?: ...)', так что я мягко прохожу при сохранении кода и стараюсь как можно меньше отправлять смешанные сигналы более поздним сопровождающим. –

1

. , Проблема с вашим Regex проста: «^» (начинается с) находится в левой части «трубы», а «$» (заканчивается) с правой стороны. Они применяются только к этой части Regex, например:

^[-$+)(}{] 
OR 
(=){1,2}$ 

. , Итак, вы говорите "_starts with one of these chars_ or _ends with one or two equal signs_", понял?

. , То, что вы хотите, чтобы поставить группу, так что «чередование» (труба) относится только к его содержанию, например:

^([-$+)(}{]|={1,2})$ 

. , Теперь вы говорите: "the text is made of either of _this list of chars_ or _one or two equal signs_".

. Amplexos.