簡體   English   中英

Java,正則表達式匹配字符串中的前10位數字,而忽略前導零

[英]Java, Regex match first 10 digits in String, disregard leading zeros

我有興趣從長字符串中提取前10個數字而忽略前導零。 此外,如果只有零,則只返回1 0,如果沒有數字,則返回空字符串。 我希望一次性find

例如:

  • "abcd00111.g2012asd"應匹配"1112012"
  • "aktr0011122222222222ddd"應匹配"1112222222"
  • "asdas000000asdasds0000"應與"0"匹配
  • "adsads.cxzv.;asdasd"應匹配""

這是我到目前為止所嘗試的: Ideone演示 - 代碼

Pattern p = Pattern.compile("[1-9]{1}+[0-9]{9}");
Matcher m = p.matcher(str);
if (m.find()) {
  String match = m.group();
  System.out.println(match);
}

問題是這個正則表達式在第一個非零之后需要9個連續數字,我需要任何9位數(其間可能是非數字字符)。

請注意,在代碼中我有if (m.find())而不是while (m.find())因為我希望在單次運行中找到匹配。

UPDATE

基於評論我明白,正則表達式不可能在單次運行中完成。

我想答案不一定是基於正則表達式,但最有效率,因為我將多次執行此方法。

一般情況下,單個find無法執行此操作。 如果您知道連續數字序列的最大數量,則可以執行此操作,但如果不知道,則不可能,至少在Java Pattern類的支持級別。 我錯了。 Kobi的評論顯示,單個正則表達式是可能的。 我將在此處復制評論:

哦,使用正則表達式可以捕獲10個數字,例如: ^[\\D0]*(\\d)\\D*(?:(\\d)\\D*(?:(\\d)\\D*(?:(\\d)\\D*(?#{6 more times}))?)?)? ,但確實很難看,而且擴展性不好。

但是,您仍然需要串聯組。 開頭的正則表達式中的邏輯非常好:由於greedy屬性,它將搜索所有前導零(如果有)之后的第一個非零數字,或者如果不存在則返回最后一個0。 -零位數。


如果你把關於效率的討論扔出門外,你想要短代碼:

String digitOnly = str.replaceAll("\\D+", "");
String noLeadingZero = digitOnly.replaceFirst("^0+", "");
String result = digitOnly.isEmpty() ? "" :
                noLeadingZero.isEmpty() ? "0" : 
                noLeadingZero.substring(0, Math.min(noLeadingZero.length(), 10));

坦率地說,使用StringBuilder循環遍歷字符串就足夠了,它應該比正則表達式解決方案更快。

StringBuilder output = new StringBuilder();
boolean hasDigit = false;
boolean leadingZero = true;
for (int i = 0; i < str.length() && output.length() < 10; i++) {
    char currChar = str.charAt(i);
    if ('0' <= currChar && currChar <= '9') {
        hasDigit = true;
        if (currChar != '0') {
            output.append(currChar);
            leadingZero = false;
        } else if (!leadingZero) { // currChar == 0
            output.append(currChar);
        } // Ignore leading zero
    }
}

String result = !hasDigit ? "" :
                output.length() == 0 ? "0" :
                output.toString();

性能測試代碼 請注意,您應該調整參數以使其類似於實際輸入,以便獲得良好的近似值。 我懷疑循環方法比任何涉及正則表達式的方法都要慢。 但是,這種差異僅在大規模上才有意義。

String test = "sdfsd0000234.432004gr23.022";
StringBuilder sb = new StringBuilder();
for(int i=0;i<test.length();i++) {
    if(Character.isDigit(test.charAt(i))) 
        sb = sb.append(test.charAt(i));
}
String result = sb.toString();
result = result.replaceFirst("^0*", "");  //Remove leading zeros
System.out.println(result);               //Will print 23443200423022

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM