Анализатор и валидатор числовых выражений CSS

#php #regex

#php #регулярное выражение

Вопрос:

Мне нужно для моего текущего проекта анализировать и проверять числовые выражения, аналогичные тем, которые используются в CSS3 :nth-child() . По сути, выражение an b , где a и b должно быть целочисленными значениями (как положительными, так и отрицательными). Они также могут быть равны 0 .

Несколько примеров, чтобы сделать все более понятным: 2n 1 , 2n , 4 и n 2 должны быть действительными. В основном, a и b представляют собой любые целые числа, со знаком или без знака.

Следующие примеры:

  • n (a=1, b=0)
  • n 1 (a=1, b=1)
  • 1 (a=0, b=1)
  • 2n 1 (a=2, b=1)
  • 23n 45 (a=23, b=45)
  • 2n-2 (a=2, b=-2)
  • -1 (a=0, b=-1)
  • -2n (a=-2, b=0)

все они действительны. Это должно завершиться неудачей только тогда, когда a or b не является целым числом или если в выражении присутствует какой-либо другой символ.

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

Комментарии:

1. Если отправленное выражение соответствует РЕГУЛЯРНОМУ выражению, оно должно возвращать true и, следовательно, проходить проверку. Меня больше интересует само РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ. Я использую это в PHP.

2. Пожалуйста, приведите примеры чего-то, что может быть близко, но не должно проходить проверку

3. @linkyndy, ах, извините, я прочитал «оценить», где вы сказали «проверить». Не обращайте внимания на мой комментарий.

4. На каком языке реализуется это выражение? Java? PHP? .Net? JavaScript? Кроме того, нежелательно или приемлемо иметь 1 результат для b ?

5. @CodeJockey, я реализую это на PHP. Я привел больше примеров в комментарии к вашему ответу.

Ответ №1:

РЕДАКТИРОВАТЬ: исправлено, чтобы разрешить отрицательные числа, как указано в КОНЦЕ вопроса РЕДАКТИРОВАТЬ

Если это допустимые значения:

 5n 12   3456    -5     2     123n 6  8n    13n-6    n 2
  

И они недопустимы:

 25n.1   4x 4    2n     6N-2  8n- 5   n -3  Rn T     x 1
  

затем это выражение должно проверять:

 ^(-?d (n([ -]d )?)?)$
  

Это выражение говорит:

 ^           # Assert beginning of line
(d         # Match one or more digits
  (n        #   TRY to Match a literal n character
    ( d   #     TRY to match a literal plus character followed by one or more digits
    )?      #     END TRY
  )?        #   END TRY
)           # End Match
$           # Assert at end of string
  

TRY s попытается выполнить проверку, но не будет возражать, если его там нет.

Редактировать:

Хотя приведенное выше выражение должно проверяться, это выражение должно давать именно те результаты, которые вы ищете, используя именованные группы захвата a и b , и положительный прогноз для захвата только чисел для a и b и для исключения символа, но только для захвата - символа для отрицательных чисел:

 ^(?:(?:(?P<a>-?d*)n)?(?=[ -]?d |$) ?(?P<b>-?d )?)$
  

Результаты должны быть следующими:

  source     a       b
------     ------  ------
 5n 12      5       12
 3456               3456
 2                  2
 123n 6     123     6
 8n         8           
 -5                 -5
 13n-6      13      -6
 n 2                2
 n
  

Поскольку я не совсем уверен, как <null value or nothing> ,zero length or null string> работает дихотомия vs в PHP и preg_match_all , я бы рекомендовал использовать это выражение, если у вас возникнут какие-либо проблемы с различением результатов для n 2 и 2 :

 ^(?:(?P<n>(?P<a>-?d*)n)?(?=[ -]?d |$) ?(?P<b>-?d )?)$
  

Это захватывает все выражение «n» или ничего, если его нет, для n 2 , 2 , и 12n 2 , это производит:

  source    n        a       b
------     ------  ------  ------
 2                          2
 n 2       n                2
 12n 2     12n      12      2
  

Комментарии:

1. n 2 должно быть допустимым. В принципе, a и b являются любыми целыми числами, подписанными или беззнаковыми. n (a=1, b=0) , n 1 (a=1, b=1) , 1 (a=0, b=1) , 2n 1 (a=2, b=1) , 23n 45 (a=23, b=45) , 2n-2 (a=2, b=-2) , -1 (a=0, b=-1) , -2n (a=-2, b=0) все допустимы. Это должно завершиться неудачей только тогда, когда a or b не является целым числом, или если в выражении присутствуют некоторые другие символы.

Ответ №2:

Вы хотите что-то вроде ^(?:(?:(-?d*)n)?([ -]d )?|(d ))$ .
Это вернет два числа в двух успешных группах захвата.

Комментарии:

1. Итак, это возвращает a b , правильно ли отформатированы числа и (будучи целыми числами)? Кроме того, строка не должна содержать ничего, кроме an b выражения. Вы учли это в своем фрагменте кода? Прошу прощения, но мои навыки в регулярных выражениях очень низки … 🙂

2. Он будет соответствовать, только если строка правильная. Если он соответствует, он вернет числа в виде групп захвата. Вы должны изучить регулярные выражения.

3. Спасибо за ваши объяснения. Я знаю, я должен их изучить.

4. это захватывает второе число в одну из двух групп захвата (либо вторую, либо третью) и захватывает — нет способа узнать, может ли ваш язык обрабатывать строки синтаксического анализа с ведущими , но вы могли бы это обрезать. В противном случае он действителен! ^(?:(?:(-?d )n)?([ -]?d )?)$ захватывает в 2 группы

5. @SLaks, предлагаемое вами решение также соответствует пустой строке: я не думаю, что это правильно.