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

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

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

我错过了关于正则表达式的一些事情吗? 或者这根本不可能?

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

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

说明:

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

它不是那么短,也不灵活。

如果你搜索1到19,你可以搜索“DX 1?[0-9]”,但是如果它没有在数字边界结束,很快就会变得很难看,并且更改规则不是灵活。

将字符串拆分为空白,然后使用x> 0和x <24更好地理解和更灵活。

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

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

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

  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; i0){ 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 compact(boolean transform09ToD, String... parts) { Set unique=new HashSet(); List result=new ArrayList(); 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 digits=new ArrayList(); for (int i=0; i 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 result=new ArrayList(); 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; i0) { 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]{,}, 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(>2)=(f()|[-9][0-9]{}) */ 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()); } } 

我也试图找到一系列有效范围的分钟[0-60]为我工作。

我使用的是jdk 1.8