在尝试使某些部分可选时,搞砸了正则表达式

时间:2014-05-16 15:17:43

标签: .net regex

我一直试图通过使用正则表达式来解析一个命令,以获得美好的一天。

我几次接近一个解决方案,但总是有一点点让人感到困惑。

我试图保持表达式的通用性,因为我想在不同的命令上使用它,尽管参数的数量是相同的。

我基本上最多有4个捕获组:

  1. Number1(单个区块,没有空格)
  2. Number2(单个区块,没有空格,可选)
  3. 参数1
  4. 参数2(可选)
  5. Number1& Number2由' - '分隔。 (=可选,没有' - ' no Number2)
    Number1(+ Number2)和Param1由空格分隔(=强制)
    Param1& Param2由空格分隔(=可选)

    所以命令的基本布局是:

    [Number1] - [Number2] [Param1] [Param2]

    这是一个可以预期的示例输入列表:

    123456A789C测试

    • Number1 = 123456A789C
    • Number2 = 未捕获
    • Param1 = 测试
    • Param2 = 未捕获

    123456.789C-987654Z321Y测试

    • Number1 = 123456.789C
    • Number2 = 987654Z321Y
    • Param1 = 测试
    • Param2 = 未捕获

    123456.789C test1 test2

    • Number1 = 123456.789C
    • Number2 = 未捕获
    • Param1 = test1
    • Param2 = test2

    123456.789C-987654Z321Y test1 test2

    • Number1 = 123456.789C
    • Number2 = 987654Z321Y
    • Param1 = test1
    • Param2 = test2

    我设法为上面的例子制作一个正则表达式,因为它们相当简单。 然而,我发现Param1和Param2可能是句子。 所以我们决定如果Param1或Param2包含空格,它们应该被封装在引号之间(") 但是,我们仍然希望允许输入不带引号的单个单词' ish数据,因此引号变为可选。

    1-2" test1" " test2" 也可以输入 1-2 test1 test2
    1-2" test1 test2" " test2 test3" 无法输入 1-2 test1 test2 test3 test4

    示例输入:

    123456.789C-987654Z321Y" test1 test2" " test3 test4"

    • Number1 = 123456.789C
    • Number2 = 987654Z321Y
    • Param1 = test1 test2 (请注意如何抓取报价)
    • Param2 = test3 test4 (请注意如何抓取报价)

    这是我无法让正则表达式正常工作的地方。 一旦我开始使某些部分成为可选部分,它就不会表现得像我希望它表现的那样。

    我提出的以下正则表达式与大多数情况相符:

    (?i)^(?<numbers>(?<number1>[^\s]*?)(?:[-](?<number2>[^\s]*?))?)\s(?<params>("?)(?<param1>[^"]*)\1\s("?)(?<param2>[^"]*)\2)$
    

    然而,它不接受 1测试 1-2测试 1&#34;测试&#34; 1-2&#34;测试&#34; 1&#34;测试测试&#34; 1-2&#34;测试测试&# 34;

    一些正则表达式专家可以帮我解决这个问题并解释我的表情出错了吗?

    这是我用作匹配最完整命令的起点的另一个正则表达式,例如 1-2&#34; test1 test2&#34; &#34; test3 test4&#34;

    (?i)^(?<numbers>(?<number1>.*)-(?<number2>.*))\s(?<params>"(?<param1>[^"]*)"\s"(?<param2>[^"]*)")$
    

2 个答案:

答案 0 :(得分:1)

(?<N1>[^- ]+)(-(?<N2>[^ ]+))? (?<P1>("[^"]+")|([^ ]+))( (?<P2>("[^"]+")|([^ ]+)))?

Regular expression visualization

答案 1 :(得分:1)

为了清楚起见,我删除了示例中的所有命名组。

我想出了这个

<!-- language: none -->
^([a-zA-Z0-9.]+)(-([a-zA-Z0-9.]+))?\s(([a-zA-Z][a-zA-Z0-9]*)|"[a-zA-Z 0-9]+")(\s(([a-zA-Z][a-zA-Z0-9]*)|"[a-zA-Z 0-9]+"))?

(见source

这是一个细分

  • 我们从^开始一行(确保您使用的函数可以激发您想要的选项:不区分大小写,全局匹配,多行。我已经使用了该选项在正则表达式引擎上简化)
  • 然后我们想要为强制性的第一个数字捕获一个或两个数字([a-zA-Z0-9.]+),为可选的第二个数字捕获(-([a-zA-Z0-9.]+))?
  • 我们添加了空格\s。请注意,这不能像[]一样在(([a-zA-Z][a-zA-Z0-9]*)|"[a-zA-Z 0-9]+")范围内使用,因为它们会将速记恢复为字面意义反斜杠或s。
  • 然后我们要匹配带或不带双引号"的标识符来处理这个问题。替换的第二部分添加了(\s(([a-zA-Z][a-zA-Z0-9]*)|"[a-zA-Z 0-9]+"))?
  • 第二个是可选的,但如果存在$
  • ,则以空格开头
  • 我们可以{{1}}
  • 结束