Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 查找不在其他字符串模式中的字符串_.net_Regex_Regex Lookarounds - Fatal编程技术网

.net 查找不在其他字符串模式中的字符串

.net 查找不在其他字符串模式中的字符串,.net,regex,regex-lookarounds,.net,Regex,Regex Lookarounds,我有一个用专有语言实现的经典if,else,endif 如果我有下面的字符串,我想定位[!-->Else-->语句,但只定位[!-->If-->…[!-->@EndIf-->]块中而不是的语句。因此,我希望在匹配else之前,打开和关闭ifs的次数为偶数 乱数假文 [!-->@如果(1=1)--] 是的 [!-->@如果(2=1)--] 2不是1 [!-->@其他--] 这样做吧 [!-->@EndIf--> [!-->@其他--] 1不是1 [!-->@EndIf--> 还有别的 在本例中

我有一个用专有语言实现的经典
if,else,endif

如果我有下面的字符串,我想定位
[!-->Else-->
语句,但只定位
[!-->If-->…[!-->@EndIf-->]
块中而不是的语句。因此,我希望在匹配
else
之前,打开和关闭
if
s的次数为偶数


乱数假文 [!-->@如果(1=1)--] 是的 [!-->@如果(2=1)--] 2不是1 [!-->@其他--] 这样做吧 [!-->@EndIf--> [!-->@其他--] 1不是1 [!-->@EndIf--> 还有别的
在本例中,我想定位第二个
else
,而不是第一个,因为它位于
if/endif
块内


我现在已经花了无数个小时与消极和积极的期待落后,无法让它工作

您可以使用此正则表达式作为匹配组
值的一部分来检索每个if块的内容。最外层的匹配是阵列中的最后一个匹配:

(?<=\bif)(?>if(?<DEPTH>)|(?<VALUE-DEPTH>)endif|.?)*(?(DEPTH)(?!))(?=endif\b)

正如Abbondanza所提到的,如果您想用正则表达式实现这一点,您将需要平衡组。我应该警告你,这不是一个好的解决方案。尽管.NET的regex引擎是少数能够处理此类情况的引擎之一,但它仍然不是真正推荐的方法。您最好手动解析您的语言,这样可以更轻松地计算嵌套级别

无论如何,为了向您说明为什么正则表达式不适合在生产性软件中执行此任务,这里有一个regex(使用
RegexOptions.IgnorePatternWhitespace
RegexOptions.Singleline
),它仍然做出了一些简化的假设(稍后我将讨论):

(?#为后面可能出现的任何内容启动子模式并
#抑制回溯(因为备选方案是
#互斥)
(?\[!-->If\([^()]*\)--\])
#如果遇到If块,请将新捕获推到
#堆栈(因为嵌套级别升高)
|#或
(?)\[!-->@EndIf--\]
#如果我们可以从堆栈中弹出一个捕获,则使用
#EndIf。如果我们不能,命名组将失败。因此
#我们只能消耗比现在更多的一端
#遇到国际单项体育联合会。
|#或
(?!\[!-->@EndIf--\])。#如果此字符未标记
#EndIf,使用任意字符。
)*#尽可能长时间地重复。
$#确保我们已经到达了字符串的末尾。
(?(深度)(?!)#如果堆栈上还有任何内容,也会失败,
#因为有些Ifs没有关闭,所以
#语法无论如何都是无效的。
#如果你说服了自己,你可以省去这个
#在此之前,请确保整个嵌套语法是正确的。
)#展望结束。
现在这已经是一头野兽了,如果没有这本评论小说,几乎没有人会理解

但我提到了简化假设。给你

  • 我不允许在
    If
    条件中使用任何类型的括号。如果您想这样做,您还必须检查它们的正确嵌套。它比我在这里做的稍微简单一些,但仍然需要上下构建一堆括号
  • 主要问题可能是实际的匹配
    [\[]]*
    。由于我不允许任何类型的左括号,因此在
    Else
    块中不能有条件语句。现在,如果您想允许这样做,您必须将几乎整个内容再次复制到实际匹配中,以便您知道哪些
    if
    s和
    EndIf
    s在
    Else
    中,哪些在后面

  • 你看,要得到一个100%覆盖所有情况的正则表达式解决方案,你需要使代码完全不可维护。这就是为什么你应该认真考虑,分析字符串手动和建立某种语法树。通过这种方式,您可以获得嵌套结构的OOP表示,可以轻松地为要查找的特定
    Else
    遍历这些嵌套结构。

    [!-->Else-->]
    块中没有出现
    [!-->If-->]…[!-->EndIf-->]
    块。你是说最外面出现的
    [!-->@Else-->
    ?@Asad-当然是的。从最外层的if/else内部开始,找到嵌套if/else中没有的else。哪种语言。。。?不同语言的正则表达式实现不同您是否尝试过“平衡组”:?本文后面的示例对于解决您的问题似乎很有用。非常感谢。事实上,我现在已经完成了平衡,并且有了一个“足够好”的解决方案。它不是防弹的,因为你写起来很难。(?>(?!)。(?)(?)(?)*(?(深度)(?!)@user1844646如果你想在你的产品代码中使用这样的东西,你需要使用
    IgnorePatternWhitespace
    ,像我的答案一样格式化,并添加注释。没有人能够理解这一点(即使你一个人在做这个项目;到了圣诞节,你会忘记它的细节)
    (?<=\bif)(?>if(?<DEPTH>)|(?<VALUE-DEPTH>)endif|.?)*(?(DEPTH)(?!))(?=endif\b)
    
    (?<=else)((?!else).)+$
    
    (?<=\[!--@Else--\])      # Make sure that our match begins right after an else
                             # block.
    [^\[]*                   # Match as many non-[ characters as possible (the actual
                             # statement)
    (?=                      # This lookahead will assert that the previous statement
                             # was a top-level Else
      (?<Depth>)             # Push one capture onto the stack "Depth" (because, if
                             # this is one of the desired "Else"s we are exactly one
                             # level deep
      (?>                    # Start a subpattern for anything that could follow and
                             # suppress backtracking (because the alternatives are
                             # mutually exclusive)
        (?<Depth>\[!--@If\([^()]*\)--\])
                             # If we encounter an If block, push a new capture onto
                             # the stack (because the nesting level rises)
      |                      # OR
        (?<-Depth>)\[!--@EndIf--\]     
                             # IF we can pop a capture from the stack, consume an 
                             # EndIf. If we cannot, the named group will fail. Hence
                             # we can only consume one EndIf more than we already
                             # encountered Ifs.
      |                      # OR
        (?!\[!--@EndIf--\]). # If this character does not mark the beginning of an
                             # EndIf, consume an arbitrary character.
      )*                     # Repeat as long as possible.
      $                      # Make sure we have reached the end of the string.
      (?(Depth)(?!))         # If there is anything left on the stack, fail, too,
                             # because there are some Ifs that were not closed, so
                             # the syntax was invalid anyway.
                             # You can leave this out if you have convinced yourself
                             # beforehand that the overall nesting syntax is correct.
    )                        # End of lookahead.