使用正则表达式检查数字范围

发布于 2024-12-11 09:06:36 字数 186 浏览 0 评论 0原文

我正在使用正则表达式来验证字符串中的某种格式。该字符串将成为游戏规则。

示例:根据规则,“DX 3”是可以的,但是“DX 14”也可以……我知道如何查看字符串并找到一个或多个“数字”,所以问题是正则表达式将也匹配 34,并且这个数字超出了规则的“范围”...

我是否缺少有关正则表达式的某些内容来执行此操作?或者这根本不可能?

I'm using a regular expression to validate a certain format in a string. This string will become a rule for a game.

Example: "DX 3" is OK according to the rule, but "DX 14" could be OK too... I know how to look at the string and find one or more "numbers", so the problem is that the regex will match 34 too, and this number is out of "range" for the rule...

Am I missing something about the regex to do this? Or is this not possible at all?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

岁月静好 2024-12-18 09:06:36

不幸的是,没有简单的方法来定义正则表达式中的范围。如果您要使用范围 1-23,您最终会得到如下正则表达式:

([1-9]|1[0-9]|2[0-3])

说明:

  1. 值是 1-9
  2. 或值以 1 开头,后跟 0-9
  3. 或值以 2 开头然后是 0-3

Unfortunately there's no easy way to define ranges in regex. If you are to use the range 1-23 you'll end up with a regex like this:

([1-9]|1[0-9]|2[0-3])

Explanation:

  1. Either the value is 1-9
  2. or the value starts with 1 and is followed with a 0-9
  3. or the value starts with 2 and is followed with a 0-3
回眸一笑 2024-12-18 09:06:36

它不是那么短,而且不灵活。

例如,如果您搜索 1 到 19,您可以搜索“DX 1?[0-9]”,但如果它不以数字边界结束,它很快就会变得丑陋,并且更改规则并不可行灵活的。

在空白处分割字符串,然后使用 x >; 0且x<0 24更好理解,也更灵活。

It is not that short, and not flexible.

If you search for 1 to 19, you can search for "DX 1?[0-9]", for example, but if it doesn't end at a number boundary, it get's ugly pretty soon, and changing the rules is not flexible.

Splitting the String at the blank, and then using x > 0 and x < 24 is better to understand and more flexible.

野侃 2024-12-18 09:06:36

您可以使用以下格式编写正则表达式来解决您的问题。
假设您的范围是 0-15。

"^DX [0-9]|1[0-5]$" 

您甚至可以通过附加字符串根据您的范围使其动态。

You can use following format for writing a regular expression solving your problem.
Suppose your range is 0-15.

"^DX [0-9]|1[0-5]$" 

You can even make it dynamic depending on your range by appending strings.

海螺姑娘 2024-12-18 09:06:36
    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 IntelliJ IDEA. User: User Date: 28.09.2007 Time: 9:46:47 To change this template use
 * File | Settings | File Templates.
 */
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());
  }
}
    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 IntelliJ IDEA. User: User Date: 28.09.2007 Time: 9:46:47 To change this template use
 * File | Settings | File Templates.
 */
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());
  }
}
可爱暴击 2024-12-18 09:06:36

我还试图找到几分钟的有效范围
[0-60] 为我工作。

我用的是jdk 1.8

I was also trying to find a range of valid range for minutes
[0-60] worked for me.

I am using jdk 1.8 though

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文