Advanced analysis of numeric ranges from a string

I use Java to parse user-entered strings representing either single numeric values โ€‹โ€‹or ranges. The user can enter the following line:

10-19 

And his intention is to use integers from 10-19 โ†’ 10,11,12...19

The user can also specify a list of numbers:

 10,15,19 

Or a combination of the above:

 10-19,25,33 

Is there a convenient method, possibly based on regular expressions, to do this parsing? Or should I split the string using String.split() and then manually String.split() over the special characters (',' and '-' in this case?)

+7
source share
4 answers

Here's how I do it:

  • Separate using , as a separator.
  • If this matches this regex: ^(\\d+)-(\\d+)$ , then I know that I have a range. Then I will extract the numbers and create my range (it might be a good idea to make sure that the first digit is lower than the second digit because you never know ...). Then you act accordingly.
  • If this matches this regular expression: ^\\d+$ I would know that I only have 1 number, so I have a specific page. Then I will act accordingly.
+13
source

This proven (and fully commented) regex solution meets OP requirements:

Java regex solution

 // TEST.java 20121024_0700 import java.util.regex.*; public class TEST { public static Boolean isValidIntRangeInput(String text) { Pattern re_valid = Pattern.compile( "# Validate comma separated integers/integer ranges.\n" + "^ # Anchor to start of string. \n" + "[0-9]+ # Integer of 1st value (required). \n" + "(?: # Range for 1st value (optional). \n" + " - # Dash separates range integer. \n" + " [0-9]+ # Range integer of 1st value. \n" + ")? # Range for 1st value (optional). \n" + "(?: # Zero or more additional values. \n" + " , # Comma separates additional values. \n" + " [0-9]+ # Integer of extra value (required). \n" + " (?: # Range for extra value (optional). \n" + " - # Dash separates range integer. \n" + " [0-9]+ # Range integer of extra value. \n" + " )? # Range for extra value (optional). \n" + ")* # Zero or more additional values. \n" + "$ # Anchor to end of string. ", Pattern.COMMENTS); Matcher m = re_valid.matcher(text); if (m.matches()) return true; else return false; } public static void printIntRanges(String text) { Pattern re_next_val = Pattern.compile( "# extract next integers/integer range value. \n" + "([0-9]+) # $1: 1st integer (Base). \n" + "(?: # Range for value (optional). \n" + " - # Dash separates range integer. \n" + " ([0-9]+) # $2: 2nd integer (Range) \n" + ")? # Range for value (optional). \n" + "(?:,|$) # End on comma or string end.", Pattern.COMMENTS); Matcher m = re_next_val.matcher(text); String msg; int i = 0; while (m.find()) { msg = " value["+ ++i +"] ibase="+ m.group(1); if (m.group(2) != null) { msg += " range="+ m.group(2); }; System.out.println(msg); } } public static void main(String[] args) { String[] arr = new String[] { // Valid inputs: "1", "1,2,3", "1-9", "1-9,10-19,20-199", "1-8,9,10-18,19,20-199", // Invalid inputs: "A", "1,2,", "1 - 9", " ", "" }; // Loop through all test input strings: int i = 0; for (String s : arr) { String msg = "String["+ ++i +"] = \""+ s +"\" is "; if (isValidIntRangeInput(s)) { // Valid input line System.out.println(msg +"valid input. Parsing..."); printIntRanges(s); } else { // Match attempt failed System.out.println(msg +"NOT valid input."); } } } } 

Output:

 r''' String[1] = "1" is valid input. Parsing... value[1] ibase=1 String[2] = "1,2,3" is valid input. Parsing... value[1] ibase=1 value[2] ibase=2 value[3] ibase=3 String[3] = "1-9" is valid input. Parsing... value[1] ibase=1 range=9 String[4] = "1-9,10-19,20-199" is valid input. Parsing... value[1] ibase=1 range=9 value[2] ibase=10 range=19 value[3] ibase=20 range=199 String[5] = "1-8,9,10-18,19,20-199" is valid input. Parsing... value[1] ibase=1 range=8 value[2] ibase=9 value[3] ibase=10 range=18 value[4] ibase=19 value[5] ibase=20 range=199 String[6] = "A" is NOT valid input. String[7] = "1,2," is NOT valid input. String[8] = "1 - 9" is NOT valid input. String[9] = " " is NOT valid input. String[10] = "" is NOT valid input. ''' 

Note that this solution simply demonstrates how to check the input line and how to parse / extract value components from each line. It does not yet confirm that for range values โ€‹โ€‹the second integer is greater than the first. However, this logical check can be easily added.

Edit: 2012-10-24 07:00 Fixed index i for counting from scratch.

+6
source

you can use

 strinput = '10-19,25,33' eval(cat(2,'[',strrep(strinput,'-',':'),']')) 

It is best to include some input checks, as well as negative numbers will give problems with this method.

+1
source

In the simplest approach, you can use evil eval to do this

 A = eval('[10:19,25,33]') A = 10 11 12 13 14 15 16 17 18 19 25 33 

BUT , of course, you should think twice before doing this. Especially if it is a string provided by the user! Imagine what happens if the user provides any other command ...

 eval('!rm -rf /') 

You need to make sure that there is really nothing but what you want. You can do this with regexp .

-2
source

All Articles