仅提取字符的首次出现以及连字符之前和之后的所有数字

时间:2019-12-29 10:40:00

标签: java regex string stringbuffer

我遇到了这种情况,编写了一个通用函数,该函数只能从字符串中提取第一次出现的字符和所有数字。

输入字符串(说):ABC123-45DEF-GH67IJ9
输出字符串:A123-45D-G679

我已经确定了一种方法,但是程序的复杂性很高。这里有两种对我不利的情况:

  1. 我的程序输出不正确。
    输出: A123-45D-G679-(此额外的连字符是以下代码中的问题)。
  2. 我需要一种更好的方法来以不太复杂的方式完成此任务。

这是我的代码段:

package Test;

import java.util.LinkedList;

public class FirstLetterAndNumerics {

    static void firstLetterAndNumber(String string) {

        StringBuffer sb = new StringBuffer();
        LinkedList<String> ll = new LinkedList<String>();
        String[] str = string.split("-");
        boolean flag = true;

        for (int i = 0; i < str.length; i++) {

            ll.add(str[i]);
        }
        for (int j = 0; j < ll.size(); j++) {

            if (Character.isAlphabetic(ll.get(j).charAt(0))) {
                if (flag == false) {
                    sb.append("-");
                }
                sb.append(ll.get(j).charAt(0));

                for (int k = 1; k < ll.get(j).length(); k++) {
                    if (Character.isAlphabetic(ll.get(j).charAt(k))) {
                        flag = false;
                    } else if (Character.isDigit(ll.get(j).charAt(k))) {
                        sb.append(ll.get(j).charAt(k));
                    }
                }
                sb.append("-");
                flag = true;
            } else if (Character.isDigit(ll.get(j).charAt(0))) {
                sb.append(ll.get(j).charAt(0));

                for (int l = 1; l < ll.get(j).length(); l++) {

                    if (Character.isDigit(ll.get(j).charAt(l))) {
                        sb.append(ll.get(j).charAt(l));
                    } else if (Character.isAlphabetic(ll.get(j).charAt(l)) && flag == true) {
                        sb.append(ll.get(j).charAt(l));
                        flag = false;
                    }

                }
            }

        }
        System.out.println(sb);

    }

    public static void main(String[] args) {

        firstLetterAndNumber("ABC123-45DEF-GH67IJ9");
    }
}

2 个答案:

答案 0 :(得分:0)

您可以使用此(\d*)([A-Za-z]{1})[A-Z]*(\d*)[A-Z]*(\d*)正则表达式来实现更简单的方法。它会捕获组中的正确部分,因此您需要将组连接起来。

Here是正则表达式的工作方式。

此代码段附加了匹配项。

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegexMatching {


    public static void main(String a[])
    {
        String testStr="ABC123-45DEF-GH67IJ9";
        String regEx = "(\\d*)([A-Za-z]{1})[A-Z]*(\\d*)[A-Z]*(\\d*)";

        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(testStr);

        StringBuilder outStr = new StringBuilder();

        while (matcher.find()) {                
            for (int i = 1; i <= matcher.groupCount(); i++) {
                outStr.append(matcher.group(i));
            }
            outStr.append("-");
        }

        outStr.deleteCharAt( outStr.length() - 1 ); // delete the extra "-"
        System.out.println(outStr.toString());
    }
}

打印:

A123-45D-G679

最后,我不确定您想要的内容是否可以在单个组中捕获。这是我找到的解决方案。

答案 1 :(得分:0)

您正在以连字符开头分割字符串。要确保该字符串包含大写字符char和digit,并用连字符分隔,可以先使用:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class Demo2{

    public static void main (String[] args){
        System.out.print("Hello");
        WebDriver n = new ChromeDriver();
    }
}

Regex demo

然后,您可以使用2个捕获组并利用if(string.matches("[A-Z0-9]+(?:-[A-Z0-9]+)+")) { 模式。

\G

这将匹配

  • (?:(\b[0-9]*[A-Z])|\G(?!^))[A-Z]*([0-9]*) 非捕获组
    • (?:捕获第1组
      • (字边界,匹配0+个数字和单个字符A-Z
    • \b[0-9]*[A-Z]关闭第1组
    • )
    • |在上一场比赛的末尾而不是在开始时断言
  • \G(?!^)关闭非捕获组
  • )匹配0 +字符A-Z
  • [A-Z]*捕获第2组,匹配0+个数字

在替换中,使用2个捕获组([0-9]*)

Regex demo | Java demo

例如

$1$2

运行static void firstLetterAndNumber(String string) { if(string.matches("[A-Z0-9]+(?:-[A-Z0-9]+)+")) { Pattern pattern = Pattern.compile("(?:(\\b\\d*[A-Z])|\\G(?!^))[A-Z]*(\\d*)"); Matcher matcher = pattern.matcher(string); System.out.println(matcher.replaceAll("$1$2"); } } 将会输出

firstLetterAndNumber("ABC123-45DEF-GH67IJ9");