从字符串中高级解析数值范围

2022-09-03 13:22:48

我使用Java来解析用户输入的字符串,表示单个数值或范围。用户可以输入以下字符串:

10-19

他的意图是使用来自10-19 --> 10,11,12...19

用户还可以指定数字列表:

10,15,19

或上述各项的组合:

10-19,25,33

有没有一种方便的方法(也许基于正则表达式)来执行此解析?或者我必须使用 拆分字符串,然后手动迭代特殊符号(在这种情况下为','和'-')?String.split()


答案 1

这就是我要怎么做的:

  1. 使用 作为分隔符进行拆分。,
  2. 如果它与此正则表达式匹配:,则我知道我有一个范围。然后,我会提取数字并创建我的范围(确保第一个数字低于第二个数字可能是一个好主意,因为你永远不会知道...)。然后你采取相应的行动。^(\\d+)-(\\d+)$
  3. 如果它与此正则表达式匹配:我会知道我只有1个数字,所以我有一个特定的页面。然后我会采取相应的行动。^\\d+$

答案 2

此经过测试(并完全注释)的正则表达式解决方案满足 OP 要求:

Java 正则表达式解决方案

// 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.");
            } 
        }
    }
}

输出:

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.
'''

请注意,此解决方案仅演示如何验证输入行以及如何从每行解析/提取值组件。它不会进一步验证对于范围值,第二个整数是否大于第一个整数。但是,可以轻松添加此逻辑检查。

编辑:2012-10-24 07:00固定索引 i 从零开始计数。