【问题标题】:Regex to match variants of a string and left pad with zeros正则表达式匹配字符串的变体和左填充零
【发布时间】:2021-06-02 21:59:57
【问题描述】:

假设我有正在运行的系统,我可以使用正则表达式和替换字符串进行参数化,以检查一些字符串并将其中的一部分与正则表达式匹配为零。

在系统内部,系统使用标准 Java 功能进行正则表达式并且不受更改(不使用其他方法或类):

import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.List;
import static java.util.stream.Collectors.toList;

public class Main
{ // args[0]= "sample 066666 33 more text" -- will be read from database and is neither subject to change
  // args[1]= "(\\d{0,9}\\d)([ _-])([3-9][0-9])" 
  // args[2]= "$1-$3"
  public static void main (String[]args)
  {
    Pattern pattern = Pattern.compile (args[1]);

    Matcher matcher = pattern.matcher (args[0]);
    if (matcher.find ())
      {
System.out.println (matcher.replaceFirst (args[2]));
    // prints 'sample 066666-33 more text'
    // but should be 'sample 0000066666-33 more text'
      }

  }
}

这只是关于如何定义传递给 main() 的正则表达式和替换字符串,以便 a) 左填充匹配部分,最多 10 位数字和 b) 替换不同的分隔符,例如空格或_默认分隔符-

(上下文:它不是我的应用程序,所以我不能更改代码,只需在此处为这个特定用例提供这两个参数 [1] 和 [2] 的配置。在其他情况下,输入以及正则表达式可能完全不同以获得完全不同的结果。这就像为特定用例/结果使用特定正则表达式参数化通用组件)

arg[0] 的示例:

abc 1-31 def
abc 02 31 def
abc 55555_32 def
abc 066666 33 def
this value 1010101010-34 is what it should be like

应该会导致

abc 0000000001-31 def
abc 0000000002-32 def
abc 0000055555-32 def
abc 0000066666-33 def
this value 1010101010-34 is what it should be like

我设法匹配了他们

(\d{0,9}\d)([ _-])([3-9][0-9])

,但我找不到在分隔符前用零填充精确到 10 位数字的方法,而字符串中可能包含正确的左填充数字,或者由于手动输入前导零但未填充最多 10 个数字.

我找到了一个使用字典的解决方案,但并没有真正设法使用,因为我无法扩展输入 (args[0]) 但希望将字典添加到正则表达式? https://stackoverflow.com/a/48891673/16110438

我见过其他解决方案,例如拥有多个捕获组

(\d{9})|...|(\d{2})|(\d)

替换如

(?{1}$1)(?{2}$2)(?{3}$3)

但同样它不适用于填充,我不太明白 '?{1}' 真正代表什么。

你对我有什么建议吗,这可能在一次正则表达式执行中实现吗?

谢谢。

【问题讨论】:

  • 为什么不匹配-之前的所有数字并替换零?你不需要 RegEx。
  • @Tom - 你忘了说你还想用-替换其他分隔符,不是吗?
  • 正则表达式和替换字符串将由 http 调用提供并传递给 哪个 Java函数
  • 您好,更新了有关您的问题的描述。期待您的建议。 @Coli 给出的新样本我认为你的方法行不通,你还有其他想法吗?
  • 你试过String.format吗?

标签: regex


【解决方案1】:

您可以在String#formatString#replaceAllString#replace 的帮助下完成。

演示:

public class Main {
    public static void main(String[] args) {
        String [] arr = {
                "1-31",
                "02#31",
                "55555-32",
                "066666/33",
                "999999999 34",
                "1010101010-35"
        };
        
        for(String s: arr) {
            String formatted = String.format("%13s", s.replaceAll("[#/\\s]", "-")).replace(' ', '0');
            System.out.println(formatted);
        }
    }
}

输出:

0000000001-31
0000000002-31
0000055555-32
0000066666-33
0999999999-34
1010101010-35

【讨论】:

  • 大家好,这里有贡献。我刚刚更新了问题:我只是在寻找 pure regex 解决方案,而不是寻找更改 Java 代码的答案,因为我无法更改它(我什至不是可以访问代码的开发人员) 这不是我这边的问题。因此,如果有人有一个正则表达式解决方案,我可以使用它从外部配置我们的系统,并将其按原样传递给 Java 代码,那就太好了。谢谢。
  • @Tom 任何与您不同的解决方案都会更改代码。您需要更具体地了解哪些可能会发生变化,哪些可能不会发生变化。
  • @WJS 更新了描述,我希望它更清楚:-)
【解决方案2】:

替代方案:

使用正则表达式:

"(\\d{10})\\D+(\\d+)"

上下文中的正则表达式:

public static void main(String[] args) {
    String input = "1-31\n"
            + "02#31\n"
            + "55555-32\n"
            + "066666/33\n"
            + "999999999 34\n"
            + "1010101010-35";

    String paddedInput = Pattern.compile("^", Pattern.MULTILINE).matcher(input).replaceAll("0".repeat(9));
    Matcher matcher = Pattern.compile("(\\d{10})\\D+(\\d+)", Pattern.MULTILINE).matcher(paddedInput);
    while(matcher.find()) { // adjusting the padding and numbers in group 1 to a total of 10 digits
        System.out.printf("%s-%s%n", matcher.group(1), matcher.group(2));
    }
}

输出:

0000000001-31
0000000002-31
0000055555-32
0000066666-33
0999999999-34
1010101010-35

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 2012-06-05
    • 2013-12-25
    • 1970-01-01
    相关资源
    最近更新 更多