2013-10-09 194 views
1

我有一个关于正则表达式编号范围的查询。正则表达式编号范围

  1. 15到无穷?
  2. 20到无穷?

我知道10到无穷远 - >[1-9][0-9]+[1-9][0-9]*的作品。

谢谢。
B

+0

对于15,只要使用'或'逻辑:例如'1 [5-9] | [2-9] \ d | \ d {3,}' - 匹配15-19或20-99,或任意数量的3位或更多位数。 20类似但更容易,因为它基本上与10 – SmokeyPHP

+1

'[1-9] [0-9] *一样也会匹配1-9否? '*'为0或更多 –

+2

为什么正则表达式呢?我有一种感觉,这可能是[XY问题](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。你想达到什么目的?用什么语言? – SmokeyPHP

回答

1

是的,有。我在one of my questions中遇到了这个问题 - 我以有效的代码结束了范围的正则表达式(即[a, b])。你的条件是[a, b] U (b, +inf),其中b是最高的数字,与9组合仅具有数字相同的计数为a

你的问题可以解决很简单。即对于15 b将是99,对于300 b将是999 e t.c.第二部分(b, +inf)是一个简单的部分 - 它只是[1-9][0-9]{c, }其中cb中的位数。

所以,做一个长话短说:

  • 查找c。它只是string_length(a)(它不是一个真正的功能,它是伪)
  • 找到b。这只是repeat_string('9', c)(它不是一个真正的功能,它是伪)
  • 找到正则表达式的第一部分:[A,B] - 在我的问题,你可以看到逻辑(其他答案有太多好)
  • 建立的第二部分你的正则表达式:(b, +inf)
  • 收集你的两部分

但是。对我而言,这是一件好奇的事情,而在真实情况下:请勿对此使用正则表达式。简单的$x>a检查要容易得多。

1

如前所述,正则表达式是不是比较次数的工具 - 尤其是你的母语有一个更简单的替代方案,是if(a > 15)

然而,如果这仅仅是好奇或脑筋急转弯锻炼,它肯定是值得测试一个人的正则表达思想过程。我已经包括以下解决方案:

15以上= [1-9]\d{2,}|1[5-9]|[2-9]\d

20以上= [1-9]\d{2,}|[2-9]\d

0

尝试此

对于15+:

/^(?:[1][5-9]|(?:[2-9][0-9]+)|(?:[1-9][0-9][0-9]+))$/ 

对于20+:

/^((?:[2-9][0-9]+)|(?:[1-9][0-9][0-9]+))$/ 

您可以在this链接测试这个正则表达式。

0
package dev.dump; 

import java.text.MessageFormat; 
import java.util.ArrayList; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 
import java.util.Collections; 
import java.util.Locale; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

/** 
* Created by NikonDSL 
*/ 
class NumberDiapasone2RegExp { 
    private static final String invalidArgumentEmpty="Invalid argument \"{0}\" was found! {1}"; 
    private static final Pattern pattern=Pattern.compile("^(\\d+)-(\\d+)?$"); 
    private String src; 
    private String result=""; 
    private Long left; 
    private Long right; 
    private boolean transform09ToD; 

    public NumberDiapasone2RegExp(final String src) { 
    this(src, false); 
    } 

    public NumberDiapasone2RegExp(final String src, final boolean transform09ToD) { 
    this.transform09ToD=transform09ToD; 
    if (src==null || src.trim().length()==0) 
      throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty, 
                    src, 
                    "It cannot be empty.")); 
     if (src.indexOf("-")<0) 
      throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty, 
                    src, 
                    "It is supposed to have \"-\".")); 
     if (src.indexOf("-")!=src.lastIndexOf("-")) 
      throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty, 
                    src, 
                    "It is supposed to have only one \"-\".")); 
    Matcher syntaxChecker=pattern.matcher(src); 
    if (!syntaxChecker.find()){ 
     throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty, 
                   src, 
                   "It is supposed to be in format \"##-##\".")); 
    } 
    this.src=src; 
    parseAndCheck(); 
    String theSameDigits=""; 
    //the same digit goes towards result 
    if (left.toString().length()==right.toString().length()){ 
     for (int i=0; i<left.toString().length(); i++){ 
     if (i<right.toString().length() && 
      left.toString().charAt(i)==right.toString().charAt(i)){ 
      theSameDigits+=left.toString().charAt(i); 
     } 
     } 
     if (theSameDigits.length()>0){ 
     this.src=this.src.replaceFirst(Pattern.quote(theSameDigits),""); 
     this.src=this.src.replaceFirst(Pattern.quote("-"+theSameDigits),"-"); 
     parseAndCheck(); 
     } 
    } 
    result=glueParts(compact(transform09ToD, toParts()));  
    Matcher m=secondCompact.matcher(result); 
    while (m.find()){ 
     result=m.group(1).replace("(","").replace(")","")+"["+m.group(2).replaceAll("[\\[\\]]","")+m.group(3).replaceAll("[\\[\\]]","")+"][0-9]"; 
     m.reset(result); 
    } 
    //compact squares again 
    StringBuffer sb=new StringBuffer(); 
    Pattern squresP=Pattern.compile("(\\[(\\d|-)+\\])"); 
    m=squresP.matcher(result); 
    while (m.find()) { 
     m.appendReplacement(sb, Matcher.quoteReplacement(compactSquares(m.group(1)))); 
    } 
    m.appendTail(sb); 
    result=sb.toString(); 
    result=result.replaceAll("\\[(\\d)-\\1\\]","$1"); 
    result=result.replaceAll("\\[(\\d)\\]","$1"); 
    result=result.replace("{1}","").replace("{0,1}","?"); 
    if (result.indexOf("|")>=0) result=theSameDigits+"("+result+")"; 
    else result=theSameDigits+result; 
    if (result.startsWith("(") && result.endsWith(")")) result=result.substring(1, result.length()-1); 
    } 

    private static Pattern secondCompact=Pattern.compile("(.*)(\\[\\d-?\\d\\]|\\d)\\[0-9\\]\\|(\\[\\d-?\\d\\]|\\d)\\[0-9\\]"); 

    static List<String> compact(boolean transform09ToD, String... parts) { 
     Set<String> unique=new HashSet<String>(); 
     List<String> result=new ArrayList<String>(); 
     for (String part : parts){ 
      if (part==null || part.length()==0) continue; 
      part=compactSquares(part); 
      part=part.replaceAll("\\[(\\d)\\]","$1"); 
      if (part.indexOf("[0-9]")>=0){ 
       if (transform09ToD) part=part.replace("[0-9]","\\d"); 
      } 
      //[0-3][0-9]|4[0-9]=>[0-34][0-9] 
      //[023][0-9]|4[0-9]=>[0234][0-9] 
      //[02345789]=>[02-57-9] 
      Matcher m=secondCompact.matcher(part); 
      if (m.find()){ 
       part=m.group(1).replace("(","").replace(")","")+"["+m.group(2).replaceAll("[\\[\\]]","")+m.group(3).replaceAll("[\\[\\]]","")+"][0-9]"; 
      } 
      part=part.replaceAll("\\[(\\d)-\\1\\]","$1"); 
      if (unique.add(part)) result.add(part); 
     } 
     return result; 
    } 

    static String compactSquares(String src){ 
    boolean inSquares=false; 
    if (src.startsWith("[") && src.endsWith("]")){ 
     inSquares=true; 
     src=src.substring(1,src.length()-1); 
    } 
    StringBuffer sb=new StringBuffer(); 
    if (!src.contains("-")) { 
     List<Integer> digits=new ArrayList<Integer>(); 
     for (int i=0; i<src.length();i++){ 
     digits.add(Integer.parseInt(""+src.charAt(i))); 
     } 
     Collections.sort(digits); 
     for (Integer s : digits){ 
     sb.append(s); 
     } 
     src=sb.toString(); 
     sb.setLength(0); 
    } 
    int firstChar = -2; 
    int lastChar = -2; 
    int currentChar; 
    for (int i=0; i<src.length(); i++) { 
     currentChar=src.charAt(i); 
     if (currentChar == lastChar + 1) { 
     lastChar = currentChar; 
     continue; 
     } 
     if (currentChar == '-' && i+1 < src.length()) { 
     lastChar = src.charAt(i + 1) - 1; 
     continue; 
     } 
     flush(sb, firstChar, lastChar); 
     firstChar = currentChar; 
     lastChar = currentChar; 
    } 
    flush(sb, firstChar, lastChar); 
    return (inSquares?"[":"")+sb.toString()+(inSquares?"]":""); 
    } 

    private static void flush(StringBuffer sb, int firstChar, int lastChar) { 
    if (lastChar<=0) return; 
    if (firstChar==lastChar) { 
     sb.append((char)firstChar); 
     return; 
    } 
    if (firstChar+1==lastChar){ 
     sb.append((char)firstChar); 
     sb.append((char)lastChar); 
     return; 
    } 
    sb.append((char)firstChar); 
    sb.append('-'); 
    sb.append((char)lastChar); 
    } 

    static String glueParts(List<String> parts) { 
     if (parts==null || parts.isEmpty()) return ""; 
     if (parts.size()==1) return parts.get(0); 
     StringBuilder result=new StringBuilder(128); 
     for (String part : parts){ 
      result.append(part); 
      result.append("|"); 
     } 
     result.deleteCharAt(result.length()-1); 
     return result.toString(); 
    } 

    private String[] toParts() { 
    List<String> result=new ArrayList<String>(); 
    if (getNumberOfDigits(left)>2 || getNumberOfDigits(right)>2) { 
     result.add(startPart(left)); 
    } 
    long leftPart=left; 
    long rightPart=right; 
    if (!String.valueOf(left).matches("10*")) leftPart=toPower(left); 
    if (!String.valueOf(right).matches("10*")) rightPart=toPower(right)/10; 
    if (rightPart/leftPart>=10) { 
     result.add(speedUpPart(left, right)); 
    } 
    //for 1-2 digit process 
    if (getNumberOfDigits(left)==1 && getNumberOfDigits(right)==1){ 
     result.add("["+left+"-"+right+"]"); 
    } 
    else if (getNumberOfDigits(left)==1 && getNumberOfDigits(right)==2){ 
     if (0==Integer.parseInt(getMajorDigit(right))) { 
     result.add(getMajorDigit(left)+ 
        "["+ 
        getMajorDigit(getNumberWithoutMajorDigit(left))+ 
        "-"+ 
        getMajorDigit(getNumberWithoutMajorDigit(right))+ 
        "]"); 
     } 
     else if (1==Integer.parseInt(getMajorDigit(right))) { 
     result.add("["+ 
        getMajorDigit(getNumberWithoutMajorDigit(left))+ 
        "-9]"); 
     result.add(getMajorDigit(right)+ 
        "[0-"+ 
        getMajorDigit(getNumberWithoutMajorDigit(right))+ 
        "]"); 
     } 
     else if (2<=Integer.parseInt(getMajorDigit(right))) { 
     result.add("["+ 
        getMajorDigit(left)+ 
        "-9]"); 
     result.add("[1-"+ 
        (Integer.parseInt(getMajorDigit(right))-1)+ 
        "][0-9]"); 
     result.add(getMajorDigit(right)+ 
        "[0-"+ 
        getMajorDigit(getNumberWithoutMajorDigit(right))+ 
        "]"); 
     } 
     else throw new IllegalStateException(); 
    } 
    else if (getNumberOfDigits(left)==2 && getNumberOfDigits(right)==2){ 
     if (Integer.parseInt(getMajorDigit(left))==Integer.parseInt(getMajorDigit(right))) { 
     result.add(getMajorDigit(left)+ 
        "["+ 
        getMajorDigit(getNumberWithoutMajorDigit(left))+ 
        "-"+ 
        getMajorDigit(getNumberWithoutMajorDigit(right))+ 
        "]"); 
     } 
     else if (Integer.parseInt(getMajorDigit(left))+1==Integer.parseInt(getMajorDigit(right))) { 
     result.add(getMajorDigit(left)+ 
        "["+ 
        getMajorDigit(getNumberWithoutMajorDigit(left))+ 
        "-9]"); 
     result.add(getMajorDigit(right)+ 
        "[0-"+ 
        getMajorDigit(getNumberWithoutMajorDigit(right))+ 
        "]"); 
     } 
     else if (Integer.parseInt(getMajorDigit(left))+2<=Integer.parseInt(getMajorDigit(right))) { 
     result.add(getMajorDigit(left)+ 
        "["+ 
        getMajorDigit(getNumberWithoutMajorDigit(left))+ 
        "-9]"); 
     result.add("["+(Integer.parseInt(getMajorDigit(left))+1)+ 
        "-"+(Integer.parseInt(getMajorDigit(right))-1)+ 
        "][0-9]"); 
     result.add(getMajorDigit(right)+ 
        "[0-"+ 
        getMajorDigit(getNumberWithoutMajorDigit(right))+ 
        "]"); 
     } 
     else throw new IllegalStateException(); 
    } 
    else result.add(staticPart(right)); 
    result.add(breakPart(right)); 
    return result.toArray(new String[0]); 
    } 

    static String breakPart(final Long number) { 
    if (getNumberOfDigits(number)<=2) { 
     return ""; 
    } 
    StringBuilder result=new StringBuilder(256); 
    StringBuilder staticSection=new StringBuilder(32); 
    staticSection.append(getMajorDigit(number)); 
    for (int i=1; i<getNumberOfDigits(number)-1; i++){ 
     if (i!=1) result.append("|"); 
     result.append(staticSection.toString()); 
     staticSection.append(String.valueOf(number).charAt(i)); 
     final long nextDigit=Long.parseLong(""+String.valueOf(number).charAt(i))-1; 

     if (nextDigit<0) { 
     result.setLength(0); 
     result.append("|"); 
     continue; 
     } 
     if (nextDigit==0) result.append("0"); 
     else if (nextDigit==1) result.append("[01]"); 
     else result.append("[0-"+(nextDigit)+"]"); 
     final int numberOfRepeats=(getNumberOfDigits(number)-i-1); 
     if (numberOfRepeats==1) result.append("[0-9]"); 
     else result.append("[0-9]{"+numberOfRepeats+"}"); 
    } 
    //остаток - 2 последние цифры числа 
    if (result.length()>0) { 
     result.append("|"); 
     result.append(staticSection.toString()); 
     //последнюю цифру от 0 до нее 
     result.append("[0-"+Long.parseLong(number.toString().replaceFirst("\\d+(\\d)","$1"))+"]"); 
    } 
    if (result.length()>0) return result.toString().replace("||","|").replaceAll("^\\|",""); 
    return ""; 
    } 

    static String staticPart(final Long number) { 
    final long majorDigitMinus1=(Long.parseLong(getMajorDigit(number))-1); 
    if (majorDigitMinus1<=0) return ""; 
    if (majorDigitMinus1==2) return "[1"+majorDigitMinus1+"][0-9]{"+(getNumberOfDigits(number)-1)+"}"; 
    else if (majorDigitMinus1==1) return "1[0-9]{"+(getNumberOfDigits(number)-1)+"}"; 
    return "[1-"+majorDigitMinus1+"][0-9]{"+(getNumberOfDigits(number)-1)+"}"; 
    } 

    /** 
    * [1-9][0-9]{<X-1>,<Y-1>}, where X-number of digits of less number, Y-number of digits of greater number 
    */ 
    static String speedUpPart(Long left, Long right) { 
    //найти ближайшее до 0 то есть для 23 найти 100 для 777 найти 1000 
    //округленные до ближайшего 0 
    if (!String.valueOf(left).matches("10*")) left=toPower(left); 
    if (!String.valueOf(right).matches("10*")) right=toPower(right)/10; 
    final int leftPartRepeat=getNumberOfDigits(left)+(String.valueOf(left).matches("10*")?0:1)-1; 
    final int rightPartRepeat=getNumberOfDigits(right)+(String.valueOf(right).matches("10*")?0:1)-2; 
    if (getNumberOfDigits(left)==1 && getNumberOfDigits(right)==2) 
     return "[1-9]"; 
    else if (leftPartRepeat>=rightPartRepeat) 
     return "[1-9][0-9]{"+rightPartRepeat+"}"; 
    else 
     return "[1-9][0-9]{"+leftPartRepeat+","+rightPartRepeat+"}"; 
    } 

    private static long toPower(final Long number) { 
    final double dValue=Math.pow(10, getNumberOfDigits(number)); 
    final String value=String.format(Locale.US,"%24.0f",dValue); 
    return Long.parseLong(value.replaceFirst("\\s*(\\d+)(\\D\\d+)?","$1")); 
    } 

    private static int getNumberOfDigits(long number){ 
    return (String.valueOf(number).length()); 
    } 
    private static String getMajorDigit(long number){ 
    return (String.valueOf(number).substring(0,1)); 
    } 
    private static long getNumberWithoutMajorDigit(long number){ 
    return Long.parseLong(String.valueOf(number).replaceFirst("\\d(\\d+)","$1")); 
    } 

    /** 
    * f(<n>>2)=<major digit>(f(<n-1>)|[<major digit+1>-9][0-9]{<n-1>}) 
    */ 
    static String startPart(long number) { 
    int i=getNumberOfDigits(number); 
    if (i==1) { 
     if (number==9) return "9"; 
     else if (number==8) return "[89]"; 
     return "["+number+"-9]"; 
    } 
    final long majorPlusOne=Long.parseLong(getMajorDigit(number))+1; 
    final int numberOfDigitsMinusOne=getNumberOfDigits(number)-1; 
    String result = (majorPlusOne < 10 ? "(" : ""); 
    result+=getMajorDigit(number); 
    result+=startPart(getNumberWithoutMajorDigit(number)); 
    result+=result.indexOf("|")<0 && majorPlusOne<10 && majorPlusOne!=numberOfDigitsMinusOne && numberOfDigitsMinusOne>1?"{"+numberOfDigitsMinusOne+"}":""; 
    result+=(majorPlusOne < 10 
      ? "|[" + majorPlusOne + "-9][0-9]"+(numberOfDigitsMinusOne > 1 ? "{" + numberOfDigitsMinusOne + "}" : "") 
      : ""); 
    result+=(majorPlusOne < 10 ? ")" : ""); 
    return result; 
    } 

    private void parseAndCheck() { 
    Matcher matcher=pattern.matcher(src); 
    matcher.find(); 
    try{ 
     left=Long.parseLong(matcher.group(1)); 
     right=Long.parseLong(matcher.group(2)); 
    } 
    catch(Exception ex){ 
     left=right+1; 
    } 
    if (left>right){ 
     throw new IllegalArgumentException(MessageFormat.format(invalidArgumentEmpty, 
                   src, 
                   "Left part must be less than right one.")); 
    } 
    } 

    public String getPattern() { 
    return result; 
    } 

    public static void main(String[] args) { 
     System.err.println(new NumberDiapasone2RegExp(args[0]).getPattern()); 
    } 
}