恰好与正则表达式匹配一次

时间:2015-07-06 10:10:56

标签: c# regex

考虑M,T,W,TH,F,S,SU是星期几。

我有正则表达式,除了一个没有工作日序列的场景,即没有MTWTH之外,效果很好, FSSU位于字符串内的预期位置。

例如,q10MT有效但q10HT无效。

以下是我的表达:

string expression = "q(\\d*)(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)?";

如果是q10MT,则输出为q10MT这是正确的,但如果q10HT的输出为q10这是不正确的,我的正则表达式应该返回no没有匹配时的值或空字符串。

为了实现这一目标,我需要做出哪些改变?

4 个答案:

答案 0 :(得分:5)

你可以通过积极的预测实现它:

q(\\d*)(?=(?:M|T(?!H)|W|TH|F|S(?!U)|SU))(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)?

或者,正如@Taemyr所指出的,更短的等价物

q(\\d*)(?=(?:M|TH?|W|TH|F|SU?))(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)?

这是demo

(?=(?:M|TH?|W|F|SU?))前瞻确保在前瞻后的备用列表中至少有一个至少一个值。

C#正则表达式用法:

var rx = new Regex(@"q(\d*)(?=(?:M|TH?|W|TH|F|SU?))(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)?");
var result = rx.Match("q10MSUT").Value;

结果:

enter image description here

答案 1 :(得分:1)

以下内容如何:

q(\d*)(M|TH?|W|F|SU?)+

请参阅http://www.redmine.org/boards/2/topics/6719?r=6789,其中包含有关匹配和不匹配的示例。这个正则表达式的关键变化是,这个使用+要求至少一个匹配。

请注意,此解决方案并不要求日期有序,并且允许跳过评论中指定的日期并不重要。

编辑:OP在评论中表示他每天只需要一场比赛,而这个解决方案没有考虑到这一点。

答案 2 :(得分:1)

如果顺序无关紧要,你需要做这样的事情;

private void InitializeComponent()
    {
        this.label1 = new System.Windows.Forms.Label();
        this.textBox1 = new System.Windows.Forms.TextBox();
        this.SuspendLayout();
        // 
        // label1
        // 
        this.label1.AutoSize = true;
        this.label1.Location = new System.Drawing.Point(6, 6);
        this.label1.Name = "label1";
        this.label1.Size = new System.Drawing.Size(35, 13);
        this.label1.TabIndex = 0;
        this.label1.Text = this.LabelText;//Oooppsss!

如果q后跟一些数字,然后是一个或多个工作日,则匹配。工作日的顺序无关紧要,负面的背后保证不会发生工作日不止一次。

每个工作日都会在其自己的捕获组中捕获,并且该组的名称可以在以后提取。 “q10MTsomething”将在“数字”捕获组中捕获“q10MT”,在“星期一”捕获组中捕获M,在“星期二”捕获组中捕获T,其他捕获组将为空。 “q10TFMother”将捕获“q10TFM”,如上例所示捕获,加上“星期五”捕获组中的F. “q10TFMT”将捕获具有捕获组的“q10TFM”,如上例所示。 “q10HT”不匹配。

demo

请注意,这是regexp字符串。如果在代码中输入,则可能需要转义q(?<number>\d+)((?<monday>(?<!M\D*)M)|(?<tuesday>(?<!T(?!H)\D*)T(?!H))|(?<wednesday>(?<!W\D*)W)|(?<thursday>(?<!TH\D*)TH)|(?<friday>(?<!F\D*)F)|(?<saturday>(?<!S(?!U)\D*)S(?!U))|(?<sunday>(?<!SU\D*)SU))+ 以生成正确的字符串。

答案 3 :(得分:1)

问题已经回答了。即便如此,我想指出另一个想法,使用可变长度lookbehind来维护序列,该序列应为fine with .NET

q(\d*)[MTWFSUH]+(?<=q\d*(M)?(T)?(W)?(TH)?(F)?(S)?(SU)?)
  • [MTWFSUH]是有效字符列表。至少需要一个
  • 只要维持序列,就使用lookbehind进行匹配

Test at your test tool