使用正则表达式组从控制台输入中解析多个字段

Parse multiple fields from console input by using regex groups

我有 Publication 个实体:

public class Publication {
    private long id;
    private String authorName;
    private Topic topic;
    private long publicationTime;
    private String header;
    private String text;
//...
}

其中 Topic 是枚举并且有预装值:

public enum Topic {
    SALE, PURCHASE, RENT, SERVICES, DATING;
}

Publication 个实体的规则:

  1. 作者姓名可以包含拉丁字母和数字,但第一个符号必须是字母。它的长度应该在 4 到 20 个符号之间。
  2. 用户应该选择一个预安装的主题。
  3. Header 应包含 10 到 30 个符号。
  4. 文本应包含 20 到 400 个符号。

用户通过控制台工作并可以编辑发布。

这是用户应该使用的语法: [author name] [topic] [header] [text]

其中字段之间由空格分隔。

所以我想出了以下正则表达式:

([a-zA-Z]\w{3,19}) (RENT|SALE|PURCHASE|SERVICES|DATING) ((\w|\W|\s){10,30}) ((\w|\W|\s){20,400})

我解析为:

         Pattern pattern = Pattern.compile("above regex");
         Matcher matcher = pattern.matcher(input);
         if (matcher.find()) {
            String authorName = matcher.group(1);
            Topic topic = Topic.valueOf(matcher.group(2));
            String header = matcher.group(3);
            String text = matcher.group(4);
            //...
         }

但它失败了,例如这样的输入:

Alexander SALE some header This is a text for some publication

因为 Matcher 找到了四个以上的组,所以我得到:

authorName=Alexander
topic=SALE
header=header three This is a
text=a

而不是:

authorName=Alexander
topic=SALE
header=header three
text=This is a text for some publication

如何解决?

您的输入格式不明确,因此您永远无法成功解析它。您无法确定 [header] 结束和 [text] 开始的位置,因为您允许在两个值中使用 space 个字符。

我建议您更改为输入数据中不允许的分隔符(例如 ;/)。或者可能需要将 header 封装在您可以搜索的内容中,例如

Alexander SALE {some header} This is a text for some publication

如果你使用我的第二个例子,下面的模式会匹配它:

"([a-zA-Z]\w{3,19}) (RENT|SALE|PURCHASE|SERVICES|DATING) \{((?:\w|\W|\s){10,30})\} ((\w|\W|\s){20,400})"

除了添加 \{...\} 来捕获标题外,我还更正了您的部分模式。最初你有:

((\w|\W|\s){10,30})

但这会创建两个捕获组。为了避免这种情况,我把内组做成non-capturing组加上?:,如下图:

((?:\w|\W|\s){10,30})