【问题标题】:Regex Replace for [- to +] Integers in c#正则表达式替换 c# 中的 [- to +] 整数
【发布时间】:2020-12-09 19:56:55
【问题描述】:

我正在尝试使用正则表达式来格式化用户输入的数字文本, 负数和正数。

我试过这种模式

[^-.0-9]

但没有按预期工作,并且接受这样的字符串 -00-000---0000。

上网查了一下,发现了这种模式

 @"^-\d *\.?\d +$"

但是正则表达式替换不适用于这样的模式。
我也在粘贴代码。

var text = Regex.Replace(string, @"^-\d *\.?\d +$", "");

上面的代码不起作用。
如果我输入任何字符串变量 text 将包含与我输入的完全相同的字符串,而无需格式化或将其转换为正则表达式。

是代码的问题还是我看不懂的模式。

我想要这样的东西

Input Output
-9999 -9999
99ab9 999
676y7 6767
99.0hu 99.0
-99.00 -99.00

【问题讨论】:

  • 请提供一些示例输入。
  • 您可以添加一些输入示例和预期结果吗?
  • 我添加了一些输入案例以便更好地理解
  • 可能有多种方法可以清除无效字符串。例如,9-9 应该变成-9 还是99?附带说明,当您键入的符号根据任意规则消失时,这是一种糟糕的用户体验,请不要这样做。
  • 我知道,但这是一个要求。我也无法理解为什么替换功能不起作用。

标签: c# regex


【解决方案1】:

所以在你的输入字符串中,你想保留:

  • 前面没有其他连字符、数字或点的第一个连字符
    那是(?<![0-9.-].*)-
  • 前面没有其他点的第一个点
    那是(?<!\..*)\.
  • 所有数字
    那是[0-9]

这直接对应一个简单的正则表达式:

@"[0-9]|(?<!\..*)\.|(?<![0-9.-].*)-"

然后使用:

string[] inputs = { "-00-000---0000", "-9999", "99ab9", "676y7", "99.0hu", "-99.00", "9-9" };

foreach (var input in inputs)
{
    Console.WriteLine(string.Concat(Regex.Matches(input, @"[0-9]|(?<!\..*)\.|(?<![0-9.-].*)-").Cast<Match>().Select(m => m.Value)));
}

请注意,可能有多种方法可以清除无效字符串。例如,应该将9-9 转换为-9 还是99?这个特定的实现恰好与99 一起使用。

附带说明,当您键入的符号根据任意规则消失时,这是一种糟糕的用户体验,请不要这样做。

【讨论】:

  • 喜欢这个解决方案。没有考虑前瞻或简单地单独匹配每个有效字符,然后将它们全部连接起来
【解决方案2】:

所以真正的正则表达式并不是完全设计来做这种类型的事情,但是它几乎可以使用捕获组并重复调用正则表达式。

我将首先解释我的正则表达式,它何时起作用,何时以及为什么不起作用,然后如何使它起作用

正则表达式

这里是:

(^[+-]?)(?:([0-9.]+)|[^\.\d\n\s]*)+

现在来分解一下

  • (^[+-]?) 负责在行首查找一个或零个“+”或“-”实例。这周围的括号是一个捕获组,意思是如果我们在这里找到一个符号,我们将在我们的第一个“捕获组”中返回它

  • (?:)+ 表示可以出现一次或多次的“非捕获组”。这意味着我们希望将这里的所有内容组合在一起,并对其应用“+”量词,但我们不想将其作为捕获组返回

  • 接下来我们在两个不同的正则表达式之间有一个或|

  • ([0-9.]+) 是我们“捕获”您的实际数字的地方,这表示我们可以有任何数字或小数位一次或多次。这又是在一个捕获组中,这意味着我们想要返回这个结果。

  • [^\.\d\n\s]* or 中的另一个选项是匹配 不是 数字的任何内容(抱歉,我已将符号更改为在此处使用 \d,这是我的错误)、换行符或空格.这将匹配随机位于字符串中间的任何字符,例如示例 2 和 3

为什么它不完美

这个正则表达式在任何只需要捕获一组数字的情况下都可以完美地工作,除了示例 2 和 3 之外的所有内容。但是,正则表达式中的捕获组只能返回一个组,因此它们的行为是始终返回最后一组。

你可以在regex tester看到这个

否则,这样做本质上是递归的,这是正则表达式无法匹配的行为(为此,您需要一些更高级的语言解析,例如 Backus Naur 形式)

解决方案

虽然它自身的正则表达式不是递归的,但您可以反复调用它并收集所有捕获组!这个正则表达式应该对这样做很友好

使用 C# 的正则表达式库,您应该能够提取返回的捕获组,您需要执行此操作,然后在循环中删除提取的捕获(不知道 C# 是否可以这样做),直到在字符串导致没有新的捕获。将所有这些捕获存储在一个列表中将为您提供重建所需字符串所需的所有组件。

(请注意,由于正则表达式匹配它找到的捕获的 last 实例,因此数字将在结果中以相反的顺序排列。您可以通过分隔任何非数字/小数点结果来解决此问题从列表中取出,然后反转列表并将 +/- 添加到开头(如果有的话)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 2022-06-12
    • 1970-01-01
    • 2023-04-07
    • 2016-11-12
    • 1970-01-01
    相关资源
    最近更新 更多