用于有条件地格式化数字字符串的正则表达式

本文关键字:字符串 正则表达式 数字字符 数字 有条件 格式化 用于 | 更新日期: 2023-09-27 18:02:39

删除了原始问题


我正在寻找一个正则表达式,它将包含特殊字符、字符和数字的字符串格式化为仅包含数字的字符串。在某些特殊情况下,仅将所有非数字字符替换为"(空(是不够的。

1.( 括号中的零。

  • 如果括号 (0( 中只有零,如果是第一个括号对,则应删除这些零。(不应删除仅包含零的第二个括号对(

2.( 前导零。

  • 应删除所有前导零(忽略括号(

为了更好地理解,示例:

  • 123 (0) 123 would be 123123 (zero removed)
  • (0) 123 -123 would be 123123(zero and all other non-numeric characters removed)
  • 2(0) 123 (0) would be 21230 (first zero in brackets removed)
  • 20(0)123023(0) would be 201230230 (first zero in brackets removed)
  • 00(0)1 would be 1(leading zeros removed)
  • 001(1)(0) would be 110 (leading zeros removed)
  • 0(0)02(0) would be 20 (leading zeros removed)
  • 123(1)3 would be 12313 (characters removed)

用于有条件地格式化数字字符串的正则表达式

仅当(0)不在字符串的开头时,才可以使用回溯来匹配它,并像现在一样替换为空字符串。

(删除原始解决方案(


再次更新以反映新要求

匹配

前导零,仅当(0)是第一个带括号的项目时才匹配,并匹配任何非数字字符:

^[0'D]+|(?<=^[^(]*)'(0')|'D

请注意,大多数正则表达式引擎不支持可变长度的回溯(即使用像 * 这样的量词(,因此这仅适用于少数正则表达式引擎-- .NET就是其中之一。

^[0'D]+      # zeroes and non-digits at start of string
|            # or
(?<=^[^(]*)  # preceded by start of string and only non-"(" chars
'(0')        # "(0)"
|            # or
'D           # non-digit, equivalent to "[^'d]"

(在 regexhero.net 测试(


您现在已经多次更改和添加了要求。对于这样的多个规则,最好单独为它们编码。如果一个条件匹配并导致另一个条件在应该匹配时不匹配,则调试可能会变得复杂且困难。例如,在单独的步骤中:

  1. 根据需要删除带括号的项目。
  2. 删除非数字字符。
  3. 删除前导零。

但是,如果您绝对需要在单个正则表达式中匹配这三个条件(不推荐(,那么就在这里。

如果您可以使用多个通道,正则表达式会变得非常简单。我认为如果它不是字符串中的第一件事,您可以进行第一次传递以删除您的 (0(,然后删除非数字:

var noMidStrParenZero = Regex.Replace(text, "^([^(]+)'(0')", "$1");
var finalStr = Regex.Replace(noMidStrParenZero, "[^0-9]", "");

避免了很多正则表达式的疯狂,并且在某种程度上也是自我记录的。

编辑:此版本也应该适用于您的新示例。

这个正则表达式应该非常接近您正在搜索的正则表达式。

(^[^'d])|([^'d](0[^'d])?)+

(您可以替换空字符串捕获的所有内容(

编辑:

您的请求不断发展,现在变得复杂,只需一次传递即可处理。 假设您总是在括号组之前有一个空格,您可以使用这些传递(保持此顺序(:

string[] entries = new string[7] {
    "800 (0) 123 - 1",
    "800 (1) 123",
    "(0)321 123",
    "1 (0) 1",
    "1 (12) (0) 1",
    "1 (0) (0) 1",
    "(9)156 (1) (0)"
};
foreach (string entry in entries)
{
    var output = Regex.Replace(entry , @"'(0')'s*'(0')", "0");
    output = Regex.Replace(output, @"'s'(0')", "");
    output = Regex.Replace(output, @"[^'d]", "");
    System.Console.WriteLine("---");
    System.Console.WriteLine(entry);
    System.Console.WriteLine(output);
}
(?:     # start grouping
    ^   # start of string
    |   # OR
    ^'( # start of string followed by paren
    |   # OR
    'd  # a digit
)       # end grouping
(0+)    # capture any number of zeros
|       # OR
([1-9]) # capture any non-zero digit

这适用于所有示例字符串,但整个表达式确实与后跟零的(匹配。 可以使用 Regex.Matches 通过全局匹配获取匹配集合,然后将所有匹配的组联接到一个字符串中以仅获取数字(或仅删除任何非数字(。