什么是正则表达式来替换/删除 END 之前没有未结束的 START?
Posted
技术标签:
【中文标题】什么是正则表达式来替换/删除 END 之前没有未结束的 START?【英文标题】:What would be a regex to replace/remove END where its not been preceded by an unended START? 【发布时间】:2011-05-21 22:47:35 【问题描述】:什么是正则表达式 (php) 来替换/删除(使用 preg_replace()
)END 之前没有未结束的 START?
这里有几个例子可以更好地描述我的意思:
示例 1:
输入:
sometext....END
输出:
sometext.... //because theres no START, therefore no need for the excess END
示例 2:
输入:
STARTsometext....END
输出:
STARTsometext....END //because its preceded by a START
示例 3:
输入:
STARTsometext....END.......END
输出:
STARTsometext....END....... //because the END is not preceded by a START
希望有人能提供帮助?
谢谢。
【问题讨论】:
如果你想要一个解析器,你需要写一个解析器。 一旦您必须识别嵌套分隔符的级别(括号、括号、开始/结束等),您可能应该考虑使用解析库,甚至滚动您自己的简单下推自动机,而不是正则表达式。即使您平台的正则表达式库支持使这成为可能的扩展,该解决方案也可能很脆弱且难以维护。 我不是在寻找一个解析器,它更像是一个小的正则表达式来修复多余的 END。我的正则表达式技能有限,因为我不确定如何检查它是否没有被 START 替换? 这不是一个可以用正则表达式匹配的模式。没有人能够为您提供一个小的正则表达式来执行此操作。这与您的技能无关。 实际上,我很确定有一个小的正则表达式可以删除那些END
s,但有一些澄清:1. 每行中有多少个开始/结束序列? 2. 可以嵌套吗? 3. Start
是否应该始终紧跟在前一个 End
之后,例如 S...ES...E
或 ...S...E.....S...E...E
?
【参考方案1】:
假设您不是在寻找嵌套对,有一个简单的解决方案可以去除多余的 END。考虑:
$str = preg_replace("/END|(START.*?END)/", "$1", $str);
这有点向后替换,但如果您了解引擎的工作顺序,它就很有意义。首先,正则表达式由两个主要部分组成:END|()
。从左到右尝试交替,因此如果引擎在输入字符串中看到END
,它将匹配它并继续进行下一个匹配(即再次查找END
)。
第二部分是一个捕获组,其中包含START.*?END
- 如果可能,这将匹配整个开始/结束标记。将跳过其他所有内容,直到找到另一个 END 或 START。
由于我们在替换中使用$1
,即捕获的组,因此我们只保存第二个令牌。因此,END
生存的唯一方法是进入捕获组,成为START
之后的第一个。
例如,对于文本END START 123 END abc END
。正则表达式将找到以下匹配项,并相应地保留、跳过或删除它们:
END
- 已移除
(START 123 END)
- 捕获
a
- 跳过
b
- 跳过
c
- 跳过
END
- 已删除
工作示例:http://ideone.com/suVYh
【讨论】:
使用捕获组的绝佳答案。爱它。 :)【参考方案2】:这是非常规语言的教科书示例(START 和 END 相当于左括号和右括号)。这意味着您无法将这种语言与简单的正则表达式匹配。您可以使用复杂的正则表达式达到特定的深度,但不能任意深度。
你需要编写一个语言解析器。
相关阅读:
http://www.amazon.com/Introduction-Automata-Theory-Languages-Computation/dp/0321462254/ref=sr_1_1?ie=UTF8&qid=1291768284&sr=8-1
【讨论】:
【参考方案3】:不可能为所有可能的语法编写正则表达式。对于您的情况,您可能需要一个上下文无关的解析器,例如上升或下降解析器。见:http://en.wikipedia.org/wiki/Formal_grammar
【讨论】:
以上是关于什么是正则表达式来替换/删除 END 之前没有未结束的 START?的主要内容,如果未能解决你的问题,请参考以下文章