.net 当试图使某些部分成为可选部分时,会弄乱正则表达式

.net 当试图使某些部分成为可选部分时,会弄乱正则表达式,.net,regex,.net,Regex,今天我一直在尝试使用正则表达式解析命令 我有几次接近于一个解决方案,但总有一点把事情搞砸了 我试图保持表达式的通用性,因为我希望在不同的命令上使用它,尽管参数的数量是相同的 我基本上最多有4个捕获组: 1号(单块,无空格) 数字2(单块,无空格,可选) 参数1 参数2(可选) Number1和Number2由'-'分隔(=可选,无'-'无编号2) Number1(+Number2)和Param1之间用空格(=必填)分隔 Param1和Param2由空格分隔(=可选) 因此,命令的基本布局是: [

今天我一直在尝试使用正则表达式解析命令

我有几次接近于一个解决方案,但总有一点把事情搞砸了

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

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

  • 1号(单块,无空格)
  • 数字2(单块,无空格,可选)
  • 参数1
  • 参数2(可选)
  • Number1和Number2由'-'分隔(=可选,无'-'无编号2)
    Number1(+Number2)和Param1之间用空格(=必填)分隔
    Param1和Param2由空格分隔(=可选)

    因此,命令的基本布局是:

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

    以下是可以预期的示例输入列表:

    123456A789C试验

    • 编号1=123456A789C
    • Number2=未捕获
    • 参数1=测试
    • Param2=未捕获
    123456.789C-987654Z321Y试验

    • Number1=123456.789C
    • 数字2=987654Z321Y
    • 参数1=测试
    • Param2=未捕获
    123456.789C测试1测试2

    • Number1=123456.789C
    • Number2=未捕获
    • 参数1=test1
    • 参数2=test2
    123456.789C-987654Z321Y测试1测试2

    • Number1=123456.789C
    • 数字2=987654Z321Y
    • 参数1=test1
    • 参数2=test2
    我为上面的例子编写了一个正则表达式,因为它们相当简单。 然而,我突然想到Param1和Param2可以是句子。 所以我们决定,如果Param1或Param2包含空格,则应将它们封装在引号(“) 然而,我们仍然希望允许输入不带引号的单字数据,因此引号成为可选的

    1-2“test1”“test2”也可以输入为1-2 test1 test2
    1-2“test1 test2”test2“test2 test3”不能作为1-2 test1 test2 test3 test4输入

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

    123456.789C-987654Z321Y“测试1测试2”测试3测试4

    • Number1=123456.789C
    • 数字2=987654Z321Y
    • Param1=test1test2(注意如何不捕获引号)
    • Param2=test3test4(注意引号是如何被捕获的)
    这就是我不能让正则表达式正常工作的地方。 一旦我开始使某些部件成为可选部件,它的行为就不像我希望的那样

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

    (?i)^(?<numbers>(?<number1>[^\s]*?)(?:[-](?<number2>[^\s]*?))?)\s(?<params>("?)(?<param1>[^"]*)\1\s("?)(?<param2>[^"]*)\2)$
    
    (?i)^(?(?[^\s]*?)(?:[-](?[^\s]*?)?)\s(?(“?)(?[^”]*)\1\s(“?)(?[^”]*)\2)$
    
    但是,它不接受1测试1-2测试1测试1-2测试1测试1-2测试

    一些正则表达式专业人士能帮我解释一下我的表达式哪里出了问题吗

    下面是另一个正则表达式,我使用它作为匹配最完整命令的起点,例如1-2“test1 test2”“test3 test4”

    (?i)^(?(?.*)-(?.*)\s(?(?[^]*)“\s”(?[^]*))$
    
    (?[^-]+)((?[^]+)(?(“[^”]+”)([^]+)(((?(“[^”]+”))(((?(“[^]+”))))?
    

    为了清晰起见,我从示例中删除了所有命名组

    我想到了这个

    <!-- 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]+"))?
    
    
    ^([a-zA-Z0-9.]+)([a-zA-Z0-9.]+)?\s([a-zA-Z][a-zA-Z0-9]*)|“[a-zA-Z 0-9]+”)([a-zA-Z][a-zA-Z0-9]*)|“[a-zA-Z 0-9]+”)?
    
    (见附件)

    这是一个细分

    • 我们从一行的开头开始(确保您使用的函数可以产生所需的选项:不区分大小写、全局匹配、多行。我在正则表达式引擎上使用了该选项以简化)
    • 然后,我们希望捕获一个或两个编号
      ([a-zA-Z0-9.]+)
      ,用于强制性的第一个编号,以及
      ([a-zA-Z0-9.]+)?
      ,用于可选的第二个编号
    • 我们添加了一个空格
      \s
      。请注意,这不能像您那样在
      []
      中使用,因为他们将速记还原为其字面意思反斜杠或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]+”)则以空格开头)
    • 我们可以以
      $

    你好,M'vy,谢谢你的回复,事实证明它非常有用。在测试了你在regexhero中的表达后,我注意到它并不匹配所有可能的情况。然而,经过一些小的修改,它成功了。我不得不把它改成:
    (?im)^([a-zA-Z0-9.]+)([a-zA-Z0-9.]+)?\s([a-zA-Z0-9]*|“[a-zA-Z0-9]+”)(\s([a-zA-Z0-9]*|“)$
    你自己看看:你的解释和表达让它看起来很明显,我现在觉得很愚蠢--这个表达完全符合我所有的测试用例。这个图表也很有说明性!在一些初始测试之后,我不明白为什么当我添加“^”和“$”以便在整个字符串上进行匹配时,这个表达式将不起作用。。。另一方面,它还匹配参数周围的引号(如果有)
    <!-- 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]+"))?