14

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

10-19

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

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

10,15,19

或以上组合:

10-19,25,33

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

4

4 回答 4

15

我会这样做:

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

这个经过测试(并经过充分评论)的正则表达式解决方案符合 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 从零开始计数。

于 2012-10-23T03:18:30.967 回答
1

您可以使用

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

最好是包括一些输入检查,负数也会给这种方法带来问题。

于 2012-10-22T12:46:47.783 回答
-4

在最简单的方法中,您可以eval为此使用邪恶

A = eval('[10:19,25,33]')

A =

   10    11    12    13    14    15    16    17    18    19    25    33

当然,在你这样做之前你应该三思而后行。特别是如果这是用户提供的字符串!想象一下,如果用户提供任何其他命令会发生什么......

eval('!rm -rf /')

你必须确保除了你想要的之外真的没有别的东西。您可以通过regexp.

于 2012-10-22T12:45:46.437 回答