找到字符串,然后在后面找到另一个正则表达式

时间:2016-02-24 19:07:47

标签: .net regex vb.net

我基本上有一个列出所有作业定义的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

但我想在变量存在的情况下有条件地匹配作业名称。 或者正则表达式不是实现这一目标的最佳方法吗?

2 个答案:

答案 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>[^()]*)

enter image description here

正则表达式解释:

  • (?<=/\*\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