【问题标题】:Regex help (php)正则表达式帮助 (php)
【发布时间】:2016-08-25 11:22:02
【问题描述】:

我需要有关正则表达式 (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 木材见北

注意!现在我的正则表达式中没有逗号验证,因为我使用 PHP 函数 explode 用逗号分割,然后将结果数组项传递给正则表达式。但它似乎不适用于以下输入:

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

所以,我需要以下解决方案之一:

  • 正则表达式有逗号验证(见规则)
  • 我用PHP的explode函数对输入字符串进行了爆炸,限制以下输入无效:sell 75 wood see north

谢谢。

【问题讨论】:

  • 四个你的#2 - 使用anchors,比如^(?:see (?:north|south|west|east)|(?:sell|buy) [1-9][0-9]{0,2} wood)$
  • 您没有将模式锚定到测试字符串的开头和结尾 - 因此see south sell 7 wood 给出了肯定的结果,因为单独的see south 已经满足了您的 | 连接模式的第一部分。
  • 谢谢你,它似乎工作。不过,我需要编写一些单元测试来确保它完成了它应该做的事情。当然,我会更深入地研究正则表达式。感谢您的回答!

标签: php regex


【解决方案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");

整个过程都是关于解决一个大问题并将其分解。更改其工作方式、允许哪些命令和参数等也非常非常容易。更改正则表达式会困难得多。

【讨论】:

  • 我也喜欢这种方法。问题是,有时我对如何解决具体问题感到不知所措,我不确定最好的方法是什么。
猜你喜欢
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-10
相关资源
最近更新 更多