我有 3 个数据案例:
{{test_data}}
{{!test_data}}
{{test_data1&&!test_data2}} // test_data2 might not have the !
我需要用以下方式翻译这些字符串:
mystring.test_data
!mystring.test_data
mystring.test_data1 && !mystring.test_data2
我正在摆弄超级有用的 regex101.com,我设法用Regex.Replace(str, "{{2}(?:(!?)(w*)(|{2}|&{2})?)}{2}", "$1mystring.$2 $3");
涵盖了几乎所有 3 种情况
我不知道如何使用正则表达式递归重新应用(?: )
部分,直到}}
并使用指定的替换模式将所有匹配项连接在一起
这可能吗??
编辑:这是正则表达式101页面-> https://regex101.com/r/vIBVkQ/2
我建议在这里使用更通用的解决方案,在这里使用更小、更易于阅读和维护的正则表达式:一个(最长(将用于查找您需要的子字符串(最长的(,然后使用简单的w+
模式来添加my_string.
部分,另一个将在逻辑运算符周围添加空格。较小的正则表达式将在匹配评估器中使用,以操作最长正则表达式找到的值:
Regex.Replace(input, @"{{!?w+(?:s*(?:&&|||)s*!?w+)*}}", m =>
Regex.Replace(
Regex.Replace(m.Value, @"s*(&&|||)s*", " $1 "),
@"w+",
"mystring.$&"
)
)
查看 C# 演示
主要的正则表达式匹配:
-
{{
-{{
子字符串 -
!?
- 可选的!
标志 -
w+
- 1 个或多个单词字符 -
(?:s*(?:&&|||)s*!?w+)*
- 0+ 序列:-
s*
- 0+ 空格字符 -
(?:&&|||)
-&&
或||
子字符串 -
s*
- 0+ 空格 -
!?
- 可选!
-
w+
- 1 个或多个单词字符
-
-
}}
-}}
子字符串。
正则表达式:(?:{{2}|[^|]{2}|[^&]{2})!?(w+)(?:}{2})?
正则表达式演示
C# 代码:
List<string> list = new List<string>() { "{{test_data}}", "{{!test_data}}", "{{test_data1&&!test_data2}}" };
foreach(string s in list)
{
string t = Regex.Replace(s, @"(?:{{2}|[^|]{2}|[^&]{2})!?(w+)(?:}{2})?",
o => o.Value.Contains("!") ? "!mystring." + o.Groups[1].Value : "mystring." + o.Groups[1].Value);
Console.WriteLine(t);
}
Console.ReadLine();
输出:
mystring.test_data
!mystring.test_data
mystring.test_data1&&!mystring.test_data2
我认为你不能使用递归,但通过输入模式的不同表示,你可以使用子组。注意 我使用命名捕获来稍微限制此示例中的混淆:
var test = @"{{test_data}}
{{!test_data}}
{{test_data1&&!test_data2&&test_data3}}
{{test_data1&&!test_data2 fail test_data3}}
{{test_data1&&test_data2||!test_data3}}";
// (1:!)(2:word)(3:||&&)(4:repeat)
var matches = Regex.Matches(test, @"{{2}(?:(?<exc>!?)(?<word>w+))(?:(?<op>|{2}|&{2})(?<exc2>!?)(?<word2>w+))*}{2}");
foreach (Match match in matches)
{
Console.WriteLine("Match: {0}", match.Value);
Console.WriteLine(" exc: {0}", match.Groups["exc"].Value);
Console.WriteLine(" word: {0}", match.Groups["word"].Value);
for (int i = 0; i < match.Groups["op"].Captures.Count; i++)
{
Console.WriteLine(" op: {0}", match.Groups["op"].Captures[i].Value);
Console.WriteLine(" exc2: {0}", match.Groups["exc2"].Captures[i].Value);
Console.WriteLine("word2: {0}", match.Groups["word2"].Captures[i].Value);
}
}
这个想法是无条件地阅读每个组中的第一个单词,然后可能将(|| or &&)(optional !)(word)
的 N 个组合读取为具有子捕获的单独组。
示例输出:
Match: {{test_data}}
exc:
word: test_data
Match: {{!test_data}}
exc: !
word: test_data
Match: {{test_data1&&!test_data2&&test_data3}}
exc:
word: test_data1
op: &&
exc2: !
word2: test_data2
op: &&
exc2:
word2: test_data3
Match: {{test_data1&&test_data2||!test_data3}}
exc:
word: test_data1
op: &&
exc2:
word2: test_data2
op: ||
exc2: !
word2: test_data3
请注意,行{{test_data1&&!test_data2 fail test_data3}}
不是结果组的一部分,因为它不符合语法规则。
因此,您可以从匹配结构中以相同的方式构建所需的结果:
foreach (Match match in matches)
{
var sb = new StringBuilder();
sb.Append(match.Groups["exc"].Value).Append("mystring.").Append(match.Groups["word"].Value);
for (int i = 0; i < match.Groups["op"].Captures.Count; i++)
{
sb.Append(' ').Append(match.Groups["op"].Captures[i].Value).Append(' ');
sb.Append(match.Groups["exc2"].Value).Append("mystring.").Append(match.Groups["word2"].Value);
}
Console.WriteLine("Result: {0}", sb.ToString());
}