【问题标题】:Extract only first occurrence of character and all the numbers before and after hyphen仅提取第一次出现的字符以及连字符前后的所有数字
【发布时间】:2019-12-29 10:40:00
【问题描述】:

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

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

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

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

这是我的代码 sn-p:

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");
    }
}

【问题讨论】:

  • 删除 sb.append("-");在 if 块内并写在 else bolck if(alphabetcheck){} elseIf(digitcheck){} else{sb.append("-");}
  • @AbhishekMishra:将 else 块添加到附加“-”将不起作用,因为“if”和“else if”块只会获得控制权,“else”块没有其他情况。

标签: java regex string stringbuffer


【解决方案1】:

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

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

此代码 sn-p 附加匹配项。

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

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

【讨论】:

    【解决方案2】:

    您在连字符的开头拆分字符串。要确保字符串包含由连字符分隔的大写字符和数字,您可以首先使用:

    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
      • )关闭第一组
      • |或者
      • \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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      相关资源
      最近更新 更多