【问题标题】:Regex Pattern number1 to number2正则表达式模式 number1 到 number2
【发布时间】:2015-09-16 11:07:56
【问题描述】:

我正在寻找以下行为的模式:

number1-number2
number1: Can be everything >= 0 and <= int.MaxValue
number2: Can be everything >= number1 and <= int.MaxValue

例如

"1-2" => True
"0-0" => True
"10-22" => True
"22-10" => False
"10-10" => True
"a-b" => False

如果我能直接提取两个int值也很好。

【问题讨论】:

  • 不,这不可能通过正则表达式实现..
  • @PranavCBalan 那他为什么说"22-10" =&gt; False ?查看顺序。
  • @AvinashRaj : 哦错过了.... :)
  • 为什么你不只是splitif?我认为你不能用正则表达式检查这个条件number2: Can be everything &gt;= number1 and &lt;= int.MaxValue

标签: c# regex string


【解决方案1】:

您不能使用正则表达式来比较提取的数字。您需要使用 int.TryParse 解析值并实施其他检查以获得您需要的内容。

假设您在范围内只有 整数正数,这里是 String.Splitint.TryParse 方法:

private bool CheckMyRange(string number_range, ref int n1, ref int n2)
{
    var rng = number_range.Split('-');
    if (rng.GetLength(0) != 2) 
       return false;

    if (!int.TryParse(rng[0], out n1))
       return false;
    if (!int.TryParse(rng[1], out n2))
       return false;
    if (n1 >= 0 && n1 <= int.MaxValue)
       if (n2 >= n1 && n2 <= int.MaxValue)
           return true;
    return false;
}

然后这样称呼它

int n1 = -1;
int n2 = -1;
bool result = CheckMyRange("1-2", ref n1, ref n2);

【讨论】:

  • 您不能使用正则表达式来比较提取的数字。 那不正确。这是可能的。
  • @Verarind:让 OP 和其他人决定什么对这个具体任务是正确的。我认为正则表达式在这里不合适。
  • 是的,我同意你认为正则表达式在这种情况下不合适。使用您的代码会更快 - 但这是可能的。
【解决方案2】:

解决方案

可以使用正则表达式对其进行测试 - 但您应该更喜欢代码中的解决方案,因为它会更快。这个正则表达式需要大量的回溯。此正则表达式的唯一优点是它适用于任意数字长度。

(?:^0+-\d+$)
|
(?:^(?>0*)(?<number>\d+)-(?>0*)\k<number>$)
|
(?:
    (?:^(?>0*)(?<length>\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+$)
    |
    (
        (?=^(?>0*)(?<o>\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$)
        ^
            (?>0*)
            (?<prefix>\d*)
            (?:(?<g0>0)|(?<g1>1)|(?<g2>2)|(?<g3>3)|(?<g4>4)|(?<g5>5)|(?<g6>6)|(?<g7>7)|(?<g8>8)|(?<g9>9))
            \d*
        -
            (?>0*)
            \k<prefix>
            (?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))
            \d*
        $
    )
)

这匹配每个x-y,其中x &lt;= y 用于正整​​数,包括前导零。

DEMO

它不适用于字符。

说明

我能够为所有x &lt; y 创建一个匹配x-y 的正则表达式。问题是x &lt;= y。所以我将问题拆分为x = y | x &lt; y

我们需要处理第一个或两个数字确实只包含零,但这很简单:

^0+-\d+$

现在是这样x = y

^(?>0*)(?<number>\d+)-(?>0*)\k<number>$

棘手的部分是x &lt; y

  1. 如果x 的字符长度小于yx 小于y(前导零被原子组捕获):

    ^(?&gt;0*)(?&lt;length&gt;\d)+-(?&gt;0*)(?&lt;-length&gt;\d)*(?(length)(?!))\d+

    这第一组通过每个数字一次捕获来捕获整个数字。在分隔符之后,平衡组定义清除捕获堆栈并强制至少多一位数字。

  2. 两个数字的长度相同(如果第一个数字更长,它也更大,不应该匹配)。

    为了确保两个数字的长度相同,我从断言背后的积极观察开始,以确保它与我在第 1 步中测试更长的数字的方式相同:

    (?=^(?&gt;0*)(?&lt;o&gt;\d)+-(?&gt;0*)(?&lt;-o&gt;\d)*(?(o)(?!))$)

    之后算法就很简单了。从头开始。如果当前数字相等,则转到下一个数字。如果当前的x-digit 比当前的y-digit 慢,我们就完成并找到匹配项。如果速度较慢,我们不应该匹配。这是由该模式完成的:

    ^
        (?>0*)   # cut out leeding zeros
        (?<prefix>\d*)
        .*
    -
        (?>0*)   # cut out leeding zeros
        \k<prefix>  # both numbers start with the same part
        .*
    $
    

    现在检查一位数。只有 10 种可能性 [0-9]。它们中的每一个都被一个组捕获:

    (?&lt;g0&gt;0)|(?&lt;g1&gt;1)|(?&lt;g2&gt;2)|(?&lt;g3&gt;3)|(?&lt;g4&gt;4)|(?&lt;g5&gt;5)|(?&lt;g6&gt;6)|(?&lt;g7&gt;7)|(?&lt;g8&gt;8)|(?&lt;g9&gt;9)

    现在我们可以使用条件来检查当前的y-digit 是否大于当前的x-digit。让我们显示 0 和 1:

    (?&lt;g0&gt;0)|(?&lt;g1&gt;1):如果 0 与当前 x-digit 匹配,则当前 y-digit 只有 [1-9]。如果 1 匹配只有 [2-9] 可以。这可以用于以下条件:

    (?(g0)[1-9]|...) 意味着如果g0 有捕获[1-9] 必须匹配,否则其余部分必须匹配。这合并为:

    (?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))

    最后一个技巧是g[0-8] 没有匹配的组只有g9 可用,并且没有更大的数字可能,匹配应该失败(?!)

这一切都被结合到与所有x &lt;= y 匹配x-y 的整个正则表达式中。

【讨论】:

  • 解释你在那里做了什么会很有用。
  • 我认为12346-12345 必须是False,但你的正则表达式matches it
  • @Verarind:请不要投入更多精力,或者如果你这样做了,请告诉我们你花了多长时间。我在不到 10 分钟的时间内编写了代码。
  • @stribizhev 我改变了我的答案。我花了大约 40 分钟来创建它(因为我不是母语人士,所以花了 25 分钟来创建解释)。
  • @Hoten 我添加了一个链接。
【解决方案3】:

正则表达式只能用于匹配数字。发布需要进行比较操作的帖子。

string num="number1-number2";//where (number1 & number2)=numeric val
MatchCollection stringVal= Regex.Matches(num,@"\d+");
int num1=Convert.ToInt32(stringVal[0].Value);
int num2=Convert.ToInt32(stringVal[1].Value);
if(num1>=0 && num1<=int.MaxValue && num2>=num1 && num2<=int.MaxValue)
    return true;
else
   return false;

会给你一个包含数字的数组

【讨论】:

  • 使用正则表达式我们无法进行比较,我们所能做的就是匹配并提取数据。所以一旦数据可用,比较操作应该单独处理
  • 在您的示例中 num1 始终与 num2 相同:-D
猜你喜欢
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
相关资源
最近更新 更多