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

问题描述 投票:0回答:2

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

输入字符串(说):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");
    }
}
java regex string stringbuffer
2个回答
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

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


0
投票

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

if(string.matches("[A-Z0-9]+(?:-[A-Z0-9]+)+")) {

Regex demo

然后您可以使用2个捕获组并利用\G模式。

(?:(\b[0-9]*[A-Z])|\G(?!^))[A-Z]*([0-9]*)

将匹配

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

在替换中,使用2个捕获组$1$2

Regex demo | Java demo

例如

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");将输出

A123-45D-G679
© www.soinside.com 2019 - 2024. All rights reserved.