我基本上有一个列出所有作业定义的txt文件。我想弄清楚哪些作业使用全局变量,这些变量总是采用(v(someText)格式。是否可以使用正则表达式匹配变量,然后匹配前面的作业名称?在这个例子中,我是希望将vaiable1和variable2与jobnameB匹配(理想情况下与捕获组的两次匹配)
/* ----------------- jobnameA ----------------- */
insert_job: jobnameA job_type: CMD
date_conditions: 0
alarm_if_fail: 1
/* ----------------- jobnameB ----------------- */
insert_job: jobnameB job_type: CMD
date_conditions: 1
days_of_week: tu,we,th,fr,sa
condition: s(job1) & s(job2) & (v(variable1) = "Y" | s(job1)) & (v(variable2) = "Y"
alarm_if_fail: 1
job_load: 1
priority: 10
/* ----------------- jobnameC ----------------- */
...
我可以使用以下方法匹配所有变量:
\(v\((.*?)\)
所有工作都有:
insert_job: (\S*?)\s
但我想在变量存在的情况下有条件地匹配作业名称。 或者正则表达式不是实现这一目标的最佳方法吗?
答案 0 :(得分:2)
您可以使用
(?<=/\*\s*-+\s(?<jobname>\w+)\s*-+\s*\*/(?:(?!/\*\s*-+).)*)\(v\((?<var>[^()]*)\)
请参阅regex demo。 注意您需要将正则表达式与RegexOptions.Singleline
修饰符一起使用,以便.
也可以匹配换行符。
正则表达式包含一个正面的lookbehind(在.NET中是无限宽度),在其中,有一个名为捕获组(?<jobname>\w+)
,用于捕获作业名称。它匹配全局变量的下一个/* --- job --- */
的任何字符,并将它们捕获到Group&#34; var&#34;与(?<var>[^()]*)
。
正则表达式解释:
(?<=/\*\s*-+\s(?<jobname>\w+)\s*-+\s*\*/(?:(?!/\*\s*-+).)*)
- 一个不消耗字符的正向前瞻(只是检查匹配的模式以返回true或false,如果引擎应该继续搜索后续的子模式)预期在下一个消费子模式之前找到:
/\*\s*-+\s(?<jobname>\w+)\s*-+\s*\*/
- /*
后跟0+空格,然后是1 +连字符,后跟一个空格,然后是1个或多个单词字符(捕获到 jobname 捕获group),然后是空格,连字符和*/
(?:(?!/\*\s*-+).)*
- 一个 tempered greedy token ,除了(或任何最多)/*
+空格+连字符之外的所有内容。\(v\((?<var>[^()]*)\)
- 全局变量:
\(v\(
- 文字序列(v(
(?<var>[^()]*)
- 组 var 匹配除(
和)
以外的零个或多个字符\)
- 文字)
答案 1 :(得分:1)
无需使用昂贵的可变长度后视镜 这里没有花哨的表格,图表,图表或演示链接 只是更好的解决方案...
使用C#的 Power 并完成某项工作 CaptureCollections是你的朋友。
(?ms)
^ [ \t]* /\* [\s-]*
( \w* ) # (1)
[\s-]* \*/
(?:
(?:
(?!
^ [ \t]* /\* [\s-]*
\w*
[\s-]* \*/
)
.
)*?
\(v\( [ \t]*
( \w+ ) # (2)
[ \t]* \)
)+
C#示例,请在此处查看=&gt; https://dotnetfiddle.net/Mhmjh6
string sAllJobs = @"
/* ----------------- jobnameA ----------------- */
insert_job: jobnameA job_type: CMD
date_conditions: 0
alarm_if_fail: 1
/* ----------------- jobnameB ----------------- */
insert_job: jobnameB job_type: CMD
date_conditions: 1
days_of_week: tu,we,th,fr,sa
condition: s(job1) & s(job2) & (v(variable1) = ""Y"" | s(job1)) & (v(variable2) = ""Y""
alarm_if_fail: 1
job_load: 1
priority: 10
/* ----------------- jobnameC ----------------- */
...
";
Regex RxJobs = new Regex(@"(?ms)^[ \t]*/\*[\s-]*(\w*)[\s-]*\*/(?:(?:(?!^[ \t]*/\*[\s-]*\w*[\s-]*\*/).)*?\(v\([ \t]*(\w+)[ \t]*\))+");
Match matchJobs = RxJobs.Match(sAllJobs);
while (matchJobs.Success)
{
CaptureCollection ccJobVar = matchJobs.Groups[2].Captures;
Console.WriteLine("Job Name: {0}", matchJobs.Groups[1].Value );
for (int i=0; i<ccJobVar.Count; i++)
Console.WriteLine(" var{0} = {1}", i+1, ccJobVar[i].Value);
Console.WriteLine("");
matchJobs = matchJobs.NextMatch();
}
输出
Job Name: jobnameB
var1 = variable1
var2 = variable2
VB.net示例
从C#样本翻译而来。
更新备注 - 这是一个有效的VB.net版本,
你可以在这里看到它=&gt; https://dotnetfiddle.net/2yE1ux
在我原来的翻译中,我没有意识到VB不能访问元素
使用方括号表示[]
。
显然,他们的数组访问使用括号表示法()
除此之外,它与上面的C#完全相同。
注意,我无法让样本在 CDATA 元素中工作 我在Dotnetfiddle上使用了Import Core,Xml和Linq而没有成功 我将样本转换为旧时尚的多行VB字符串方式。
VB示例
Imports System
Imports System.Text.RegularExpressions
Public Module Module1
Public Sub Main()
Dim sAllJobs As String = " /* ----------------- jobnameA ----------------- */" & Environment.NewLine & _
" " & Environment.NewLine & _
" insert_job: jobnameA job_type: CMD " & Environment.NewLine & _
" date_conditions: 0 " & Environment.NewLine & _
" alarm_if_fail: 1 " & Environment.NewLine & _
" " & Environment.NewLine & _
" " & Environment.NewLine & _
" /* ----------------- jobnameB ----------------- */ " & Environment.NewLine & _
" " & Environment.NewLine & _
" insert_job: jobnameB job_type: CMD " & Environment.NewLine & _
" date_conditions: 1 " & Environment.NewLine & _
" days_of_week: tu,we,th,fr,sa " & Environment.NewLine & _
" condition: s(job1) & s(job2) & (v(variable1) = ""Y"" | s(job1)) & (v(variable2) = ""Y"" & Environment.NewLine " & _
" alarm_if_fail: 1 " & Environment.NewLine & _
" job_load: 1 " & Environment.NewLine & _
" priority: 10 " & Environment.NewLine & _
" " & Environment.NewLine & _
" " & Environment.NewLine & _
" /* ----------------- jobnameC ----------------- */ " & Environment.NewLine & _
" ... "
Dim RxJobs As New Regex("(?ms)^[ \t]*/\*[\s-]*(\w*)[\s-]*\*/(?:(?:(?!^[ \t]*/\*[\s-]*\w*[\s-]*\*/).)*?\(v\([ \t]*(\w+)[ \t]*\))+")
Dim matchJobs As Match = RxJobs.Match(sAllJobs)
Do While matchJobs.Success
Dim ccJobVar As CaptureCollection = matchJobs.Groups(2).Captures
Console.WriteLine("Job Name: {0}", matchJobs.Groups(1).Value )
For ctr As Integer = 0 To ccJobVar.Count - 1
Console.WriteLine(" var{0} = {1}", ctr+1, ccJobVar(ctr).Value)
Next
Console.WriteLine("")
matchJobs = matchJobs.NextMatch()
Loop
End Sub
End Module
输出
Job Name: jobnameB
var1 = variable1
var2 = variable2