java - 특수문자 - 정규표현식 문자열 추출



정규 표현식으로 숫자 범위 확인 (4)

그렇게 짧지 않고 유연하지 않습니다.

1에서 19까지를 검색하면 "DX 1? [0-9]"를 검색 할 수 있습니다. 그러나 숫자 경계에서 끝나지 않으면 꽤 빨리 추악 해집니다. 규칙을 변경하는 것은 아닙니다. 융통성 있는.

공백에서 문자열을 분할 한 다음 x> 0 및 x <24를 사용하면 이해하고 융통성있게 해석하는 것이 좋습니다.

https://src-bin.com

정규식을 사용하여 문자열의 특정 형식의 유효성을 검사합니다. 이 문자열은 게임의 규칙이됩니다.

예 : "DX 3"은 규칙에 따라 OK이지만 "DX 14"도 OK 일 수 있습니다 ... 문자열을보고 하나 이상의 "숫자"를 찾는 방법을 알고 있으므로 문제는 정규식이 34도 일치하며이 숫자는 규칙의 "범위"를 벗어났습니다.

이 일을 정규식에 대해 뭔가 빠졌나요? 아니면 전혀 가능하지 않습니까?


Answer #1

나는 또한 유효한 범위의 범위를 찾기 위해 노력했다. [0-60] 나를 위해 일했다.

나는 jdk 1.8을 사용하고있다.


Answer #2

불행히도 정규식에서 범위를 정의하는 쉬운 방법은 없습니다. 1-23 범위를 사용하려면 다음과 같은 정규 표현식이 필요합니다.

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

설명:

  1. 값은 1-9입니다.
  2. 또는 값은 1부터 시작하여 0-9가옵니다.
  3. 또는 값이 2로 시작하고 0-3이 뒤에옵니다.

Answer #3
    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());
  }
}




range