Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用字符串规范解析字符串?_Java_Regex_Parsing_Regex Group_Regex Greedy - Fatal编程技术网

Java 如何使用字符串规范解析字符串?

Java 如何使用字符串规范解析字符串?,java,regex,parsing,regex-group,regex-greedy,Java,Regex,Parsing,Regex Group,Regex Greedy,我希望编写一个方法来解析包含人名和年龄的字符串。例如: Manuel 8 Mustafa 16 Zhihao 12 Itsuki 12 Louis 11 Farah 11 i、 e.字符串的规格为%N%A,其中%N表示名称,%A表示年龄 但是,字符串的规范不是固定的(例如,它可能是另一个文档中的%N年龄:%A或%N(%A)),因此解析方法应该能够将规范作为其参数之一 换句话说,解析方法的工作原理如下: Data d1 = Parser.parse("Indira 15", "%N %A");

我希望编写一个方法来解析包含人名和年龄的字符串。例如:

Manuel 8
Mustafa 16
Zhihao 12
Itsuki 12
Louis 11
Farah 11
i、 e.字符串的规格为
%N%A
,其中
%N
表示名称,
%A
表示年龄

但是,字符串的规范不是固定的(例如,它可能是另一个文档中的
%N年龄:%A
%N(%A)
),因此解析方法应该能够将规范作为其参数之一

换句话说,解析方法的工作原理如下:

Data d1 = Parser.parse("Indira 15", "%N %A");
Data d2 = Parser.parse("12 Shu-chen", "%A %N");
Data d3 = Parser.parse("Hana (12)", "%N (%A)");
Data d4 = Parser.parse("Name: Sophia [12]", "Name: %N [%A]");
public class Data {
    private String name;
    private int age;

    public Data(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // + getter and setter methods.
}

public class Parser {
    public static Data parse(String s, String specification) {
        // --- What to do here? ---
        return (new Data(name, age));
    }
}
其中
数据
解析器
的定义如下:

Data d1 = Parser.parse("Indira 15", "%N %A");
Data d2 = Parser.parse("12 Shu-chen", "%A %N");
Data d3 = Parser.parse("Hana (12)", "%N (%A)");
Data d4 = Parser.parse("Name: Sophia [12]", "Name: %N [%A]");
public class Data {
    private String name;
    private int age;

    public Data(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // + getter and setter methods.
}

public class Parser {
    public static Data parse(String s, String specification) {
        // --- What to do here? ---
        return (new Data(name, age));
    }
}

如何编写
Parser.parse
?换句话说,如何使用字符串规范解析字符串?

我将阅读该规范,并使用它解析字符串中不在%N和%a之间的所有部分,因为它们只会使逻辑复杂化。然后,您必须弄清楚您打算对这个api施加什么约束,就好像您没有对它施加约束一样,因为它是不确定的。比如说

H'mil99是模式%N%A,但是99岁的nam H'mil或9岁的H'mil9


如果您选择了名称中没有数字、年龄中没有字母的逻辑限制,则a通过在[0-9]*上执行matcher.group来识别年龄,将其与%a和%N之间的部分一起子串出来,其余部分是%N

根据
规范构建正则表达式,例如,类似于下面的内容

注意使用以确保规范中的特殊字符不被解释为正则表达式

public static Data parse(String s, String specification) {
    // Determine order of value markers
    int nameIdx = specification.indexOf("%N");
    if (nameIdx == -1)
        throw new IllegalArgumentException("Specification is missing %N: " + specification);
    int ageIdx = specification.indexOf("%A");
    if (ageIdx == -1)
        throw new IllegalArgumentException("Specification is missing %A: " + specification);

    // Build regex
    String regex;
    if (nameIdx < ageIdx) {
        regex = Pattern.quote(specification.substring(0, nameIdx)) + "(\\S+)" +
                Pattern.quote(specification.substring(nameIdx + 2, ageIdx)) + "(\\d+)" +
                Pattern.quote(specification.substring(ageIdx + 2));
    } else {
        regex = Pattern.quote(specification.substring(0, ageIdx)) + "(\\d+)" +
                Pattern.quote(specification.substring(ageIdx + 2, nameIdx)) + "(\\S+)" +
                Pattern.quote(specification.substring(nameIdx + 2));
    }

    // Parse string
    Matcher m = Pattern.compile(regex).matcher(s);
    if (! m.matches())
        throw new IllegalArgumentException("String does not fit specification '" + specification + "': " + s);
    String name, age;
    if (nameIdx < ageIdx) {
        name = m.group(1);
        age = m.group(2);
    } else {
        name = m.group(2);
        age = m.group(1);
    }
    return new Data(name, Integer.parseInt(age));
}
输出(假设
toString()
Data
类中实现)

Data[name=Indira,age=15]
资料[姓名=陈淑,年龄=12]
数据[姓名=Hana,年龄=12]
数据[姓名=索菲亚,年龄=12]

这适用于给定的数据,也适用于其他变体。但其他特殊字符可能无法正确转义

import java.util.*;
导入java.util.regex.*;
公共类解析器2{
公共静态void main(字符串[]args){
数据d1=Parser.parse(“Indira 15”,%N%A”);
Data d2=Parser.parse(“12 Shu chen”,“%A%N”);
数据d3=Parser.parse(“Hana(12)”,%N(%A)”;
数据d4=Parser.parse(“名称:Sophia[12]”,“名称:%N[%A]”);
系统输出打印项次(d1);
系统输出打印项次(d2);
系统输出打印LN(d3);
系统输出打印LN(d4);
}
}
类数据{
私有字符串名称;
私人互联网;
公共数据(字符串名称、整数年龄){
this.name=名称;
这个。年龄=年龄;
}
公共字符串toString(){
返回“name=“+name+”,“+”age=“+age;
}
}
类解析器{
私有静态映射规范=
(“%A”、“(\\d+)、“%N”、“([A-Za-z-]+)”的映射;
公共静态数据解析(字符串、字符串规范){
specification=specification.replaceAll(“\\\(”,“\\\\(”);
specification=specification.replaceAll(“\\”,“\\\”);
specification=specification.replaceAll(“\\]”,“\\\\]”);
specification=specification.replaceAll(“\\[”,“\\\\[”);
对于(字符串r:spec.keySet()){
规格=规格。更换(r,规格get(r));
}
Matcher m=Pattern.compile(specification.Matcher);
字符串m1=“”,m2=“”;
if(m.find()){
m1=m组(1);
m2=m组(2);
}否则{
返回null;
}
字符串名;
智力年龄;
如果(m1.匹配(\\d+)){
年龄=整数.parseInt(m1);
名称=平方米;
}
否则{
年龄=整数.parseInt(m2);
name=m1;
}
返回(新数据(姓名、年龄));
}
}
  • 对()和[]进行转义,以允许示例按原样工作 是正则表达式的特殊字符

  • 其中一个捕获的字符串需要测试所有要捕获的数字 允许正确转换姓名和年龄

  • 这是一种相当野蛮的方法,它不能很好地扩展


在这里,我们可以有一个表达式,并将所需输出分为两组收集,例如:

((?:\s+)?([a-z-]+)(?:\s+)?)|(\d+)
我们想要的名字在这个
([a-z-]+)
组中,年龄信息在这个
(\d+)
组中,其余的可以简单地编写脚本

试验
关键字:
Regular Expression
@RickyMo是的,我知道如何使用regex解析具有固定规范的字符串,但我不确定如何解析具有变量规范的字符串。您可以使用捕获组捕获变量。对于
%N
([0-9]+)使用
(.+)
用于
%A
并使用Java中的
Matcher.group()
检索捕获的组。示例Regex:。但是,您可能需要进行额外的分析,以确定年龄优先还是姓名优先。您的意思是:“规范”按照字面意思拼写格式,只有
%N
%A
代表姓名/年龄?然后完全这样做:从
规范中形成正则表达式,用
([\w-']+)
替换
%N
(添加名称中的任何其他内容,或使用
[^0-9]+
)和
%A
,使用
([0-9]+)
。然后,当您将
s
与此匹配时,您将捕获姓名和年龄。要查看哪个是您的规范,请再次查阅(是
%N
还是
%A
第一个?)。感谢您的建议。您确定此方法适用于
*name:John;age:15这样的字符串吗(字符串规范:
*名称:%N;年龄:%A
?@Flux好吧,不,它不会(这是一个真正的星号吗??)。您所要求的内容非常广泛,对于通用解析器来说非常有效。(请注意,您还没有给出要支持的模式的明确列表。)这将需要比适合SO帖子的代码多得多的代码。这个答案将涵盖其中一种情况(可能有一些小的调整)
(\s*([a-z-]+)\s+)|(\d+)