文本外部<;%%的Regex>;
本文关键字:Regex gt lt 文本 外部 | 更新日期: 2023-09-27 18:26:30
我需要解析这样的字符串:
text0<%code0%>text1<%code1%><%%>text3
分成两个阵列。每个区块都是可选的,所以它可以只是text
或<%code%>
,也可以是空字符串。取出代码很容易(如果我没有错的话):<%(.*?)%>
,但我需要文本方面的帮助,因为它不像代码那样没有这样的标记。
谢谢!
由于正则表达式匹配必须是连续的(即没有间隙),因此没有一个表达式可以匹配标记之外的所有文本。然而,如果您将regex与C#的string
功能结合起来,您仍然可以做到这一点,比如:
var outside = string.Join("", Regex.Split(inputString, "<%.*?%>"));
如果标记内部可能不包含百分比字符,则可以使用以下表达式优化正则表达式以避免回溯:
<%[^%]*%>
这个非常简单的Regex将执行:-):-)(这很讽刺…正则表达式是正确的,但它绝对不可读,即使是正则表达式专家也可能需要至少10分钟才能完全理解)
var rx = new Regex("((?<1>((?!<%).)+)|<%(?<2>((?!%>).)*)%>)*", RegexOptions.ExplicitCapture);
var res2 = rx.Match("text0<%code0%>text1<%code1%><%%>text3");
string[] text = res2.Groups[1].Captures.Cast<Capture>().Select(p => p.Value).ToArray();
string[] escapes = res2.Groups[2].Captures.Cast<Capture>().Select(p => p.Value).ToArray();
请记住,它需要RegexOptions.ExplicitCapture
。
正则表达式将在两个组(1和2)中捕获<% %>
外部和<% %>
内部的字符串片段。每组由多个Capture
s组成。
解释:
( ... )* The outer layer. Any number of captures are possible... So any number of "outside" and "inside" are possible
(?<1>((?!<%).)+) The capturing group 1, for the "outside"
| alternatively
<% An uncaptured <%
(?<2>((?!%>).)*) The capturing group 2, for the "inside"
%> An uncaptured %>
捕获组1:
(?<1> ... ) The name of the group (1)
内部:
((?!<%).)+ Any character that isn't a < followed by a % (at least one character)
捕获组2:
(?<2> ... ) The name of the group (2)
内部:
((?!%>).)* Any character that isn't a < followed by a % (can be empty)
请注意,如果存在未关闭的<%
!!,则此正则表达式将严重损坏!!!这个问题是可以解决的。
var rx = new Regex("((?<1>((?!<%).)+)|<%(?<2>((?!<%|%>).)*)%>|(?<3><%.*))*", RegexOptions.ExplicitCapture);
并添加
string[] errors = res2.Groups[3].Captures.Cast<Capture>().Select(p => p.Value).ToArray();
如果errors
不为空,则存在未闭合的<%
。
现在,如果您想对捕获进行排序:
var captures = res2.Groups[1].Captures.Cast<Capture>().Select(p => new { Text = true, Index = p.Index, p.Value })
.Concat(res2.Groups[2].Captures.Cast<Capture>().Select(p => new { Text = false, Index = p.Index, p.Value }))
.OrderBy(p => p.Index)
.ToArray();
现在每个捕获都有一个Index
、一个可以是Text
的true
和Escape
的false
的Text
以及一个作为Capture
的文本的Value
。
您可以使用Regex。替换
var text = Regex.Replace(input, "<%.+?%>", "");
试试这个:
class Program
{
static void Main(string[] args)
{
var input = "text0<%code0%>text1<%code1%><%%>text3";
List<string>
text = new List<string>(),
code = new List<string>();
var current = 0;
Regex.Matches(input, @"<%.*?%>")
.Cast<Match>()
.ToList().ForEach(m =>
{
text.Add(input.Substring(current, m.Index - current));
code.Add(m.Value);
current = m.Index + m.Length;
if(!m.NextMatch().Success)
text.Add(input.Substring(current, input.Length - current));
});
}
}