2016-08-25 4 views
2

Мне нужна помощь по регулярным выражениям (PHP). Поэтому у меня есть поле textarea, где пользователь может вводить заказы.Справка по регулярному выражению (php)

Например:

see north, 
see south, 
sell 7 wood, 
see west 

мне нужно регулярное выражение, которое соответствует следующим правилам:

  • Каждый заказ отделен запятой, за исключением последнего одного
  • Порядок является либо (см. север, см. юг, см. запад, см. восток) или (купить/продать% древесины). % - представляют число (максимум 999 и минимум 1 без головы нулей)

До сих пор я сделал это регулярное выражение:

preg_match("/(((see) (north|south|west|east))|((sell|buy) ([1-9][0-9]{0,2}) (wood)))/"); 

Но проблема в том, следующий вход также действует , который должен быть не: продать 75 см древесины на север (он должен быть либо продать 75 древесины ИЛИ см север)

NB! Прямо сейчас у меня нет проверки запятой в моем регулярном выражении, потому что я использую функцию PHP explode для разделения с запятыми, а затем передаю результирующие элементы массива в регулярное выражение. Но это не похоже на работу со следующим входом:

see north, 
see south  *(no comma between two orders)* 
sell 7 wood, 
see west 

Итак, мне нужно одно из следующих решений:

  • Регулярного выражение имеет запятую проверку (см правила)
  • Я взрываюсь входная строка с функцией взрыва PHP и ограничить, что следующий ввод недействителен: продать 75 деревьев см. север

Спасибо.

+0

Четыре ваших # 2 - используйте [якоря] (http://www.regular-expressions.info/anchors.html), например '^ (?: см. (?: north | south | west | east) | (?: sell | buy) [1-9] [0-9] {0,2} дерево) $ ' –

+0

Вы не привязывали свой шаблон к началу и концу тестовая строка - поэтому 'see south sell 7 wood' дает положительный результат, потому что' see south' самостоятельно уже удовлетворяет первой части вашего шаблона. – CBroe

+0

Спасибо, это сработало. Хотя, мне нужно написать некоторые модульные тесты, чтобы убедиться, что он делает то, что он должен делать. И, конечно же, я углубится в регулярные выражения. Спасибо за ответ! – Omaja7

ответ

1

Не используйте для этого регулярное выражение. Это работа для (базового) парсера.

Выполняйте все, что вам нужно, чтобы получить одну команду за раз. Например, это может быть explode. Используйте trim, если необходимо удалить пробелы с начала и конца.

Затем $parts = explode(" ",$command);

Теперь вы можете switch($parts[0]) определить, что делать на основе первого ключевого слова.

case "see": 
    if(!in_array($parts[1], ["north","south","east","west"])) { 
     throw new OutOfBoundsException("Invalid direction"); 
    } 
    // do something here 
    break; 

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

case "sell": 
    $q = intval($parts[1]); 
    if($q < 1 || $q > 999) { 
     throw new OutOfBoundsException("Invalid amount of things to sell"); 
    } 
    $what = $parts[2]; 
    if(!in_array($what, ["wood"])) { 
     throw new OutOfBoundsException("Invalid thing to sell"); 
    } 
    // do something 
    break; 

default: 
    throw new OutOfBoundsException("Invalid command"); 

Весь этот процесс связан с серьезной проблемой и ее разрушением. Также очень легко изменить, как это работает, какие команды и параметры разрешены и т. Д. Изменение регулярного выражения было бы намного сложнее.

+0

Мне тоже нравится этот подход. Дело в том, что иногда я слишком перегружен вариантами, как решить конкретную проблему, и я не уверен, что это лучший способ. – Omaja7

Смежные вопросы