Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.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 - Fatal编程技术网

Java 带分隔符的多个匹配项

Java 带分隔符的多个匹配项,java,regex,Java,Regex,这是我的正则表达式: ([+-]*)(\\d+)\\s*([a-zA-Z]+) 第1组=符号 第2组=乘数 第3组=时间单位 问题是,我想匹配给定的输入,但它可以“链接”。因此,我的输入应该是有效的,当且仅当整个模式在这些出现之间没有任何重复(空白除外)。(只有一个匹配项或多个匹配项相邻,它们之间可能有空格) 有效例子: 1day +1day -1 day +1day-1month +1day +1month +1day +1month ###+1day+1month +

这是我的正则表达式:

([+-]*)(\\d+)\\s*([a-zA-Z]+)
  • 第1组=符号
  • 第2组=乘数
  • 第3组=时间单位
问题是,我想匹配给定的输入,但它可以“链接”。因此,我的输入应该是有效的,当且仅当整个模式在这些出现之间没有任何重复(空白除外)。(只有一个匹配项或多个匹配项相邻,它们之间可能有空格)

有效例子:

1day
+1day
-1 day
+1day-1month
+1day +1month
   +1day  +1month    
###+1day+1month
+1day###+1month
+1day+1month###
###+1day+1month###
###+1day+1month###
无效示例:

1day
+1day
-1 day
+1day-1month
+1day +1month
   +1day  +1month    
###+1day+1month
+1day###+1month
+1day+1month###
###+1day+1month###
###+1day+1month###
在我的情况下,我可以使用matcher.find()方法,这可以做到这一点,但它将接受如下输入:
+1day\35;\35;+1个月
,这对我无效

有什么想法吗?这可以通过多个IF条件和多个开始和结束索引检查来解决,但我正在寻找优雅的解决方案

编辑

下面注释中建议的正则表达式([+-]*)(\d+)\s*([a-zA-Z]+)\s*)+$将部分起作用,但如果我在下面的代码中使用它,它返回的结果与我正在寻找的结果不同。 问题是我不能使用
(*我的正则表达式*)+
,因为它将匹配整个内容


解决方案可以是使用
^\s*([+-]*)(\d+)\s*([a-zA-Z]+)\s*)+$
匹配整个输入,然后使用
([+-]*)(\\d+)\\s*([a-zA-Z]+)
匹配器.find()
匹配器.group(i)
提取每个匹配项及其组。但我正在寻找更优雅的解决方案。

这应该适合您:

^\s*(([+-]*)(\d+)\s*([a-zA-Z]+)\s*)+$
首先,通过添加开头和结尾锚定(
^
$
),模式将不允许在匹配之前或之后的任何位置出现无效字符

接下来,我在重复模式前后添加了可选的空格(
\s*

最后,整个模式被封装在一个中继器中,这样它可以在一行中多次出现(
(…)+

另一方面,请注意,我还建议将
[+-]*
更改为
[+-]?
,这样它只能出现一次


您可以使用
^$
来匹配字符串的开头/结尾

^\s*(?:([+-]?)(\d+)\s*([a-z]+)\s*)+$

有关示例,请参见单元测试。基本上,您只需要允许模式重复,并强制在匹配之间除了空格之外没有其他内容发生


结合行开始/结束匹配,就完成了。

您可以在Java中使用
String.matches
Matcher.matches
来匹配整个区域

Java示例:

public class RegTest {

    public static final Pattern PATTERN = Pattern.compile(
            "(\\s*([+-]?)(\\d+)\\s*([a-zA-Z]+)\\s*)+");

    @Test
    public void testDays() throws Exception {
        assertTrue(valid("1 day"));
        assertTrue(valid("-1 day"));
        assertTrue(valid("+1day-1month"));
        assertTrue(valid("+1day -1month"));
        assertTrue(valid("   +1day  +1month   "));

        assertFalse(valid("+1day###+1month"));
        assertFalse(valid(""));
        assertFalse(valid("++1day-1month"));
    }

    private static boolean valid(String s) {
        return PATTERN.matcher(s).matches();
    }
}

你可以这样做:

String p = "\\G\\s*(?:([-+]?)(\\d+)\\s*([a-z]+)|\\z)";

Pattern RegexCompile = Pattern.compile(p, Pattern.CASE_INSENSITIVE);

String s = "+1day 1month";

ArrayList<HashMap<String, String>> results = new ArrayList<HashMap<String, String>>(); 

Matcher m = RegexCompile.matcher(s);
boolean validFormat = false;        

while( m.find() ) {
    if (m.group(1) == null) {
        // if the capture group 1 (or 2 or 3) is null, it means that the second
        // branch of the pattern has succeeded (the \z branch) and that the end
        // of the string has been reached. 
        validFormat = true;
    } else {
        // otherwise, this is not the end of the string and the match result is
        // "temporary" stored in the ArrayList 'results'
        HashMap<String, String> result = new HashMap<String, String>();
        result.put("sign", m.group(1));
        result.put("multiplier", m.group(2));
        result.put("time_unit", m.group(3));
        results.add(result);
    }
}

if (validFormat) {
    for (HashMap item : results) {
        System.out.println("sign: " + item.get("sign")
                         + "\nmultiplier: " + item.get("multiplier")
                         + "\ntime_unit: " + item.get("time_unit") + "\n");
    }
} else {
    results.clear();
    System.out.println("Invalid Format");
}
String p=“\\G\\s*(?:([-+])(\\d+\\s*([a-z]+)|\\z)”;
Pattern RegexCompile=Pattern.compile(p,Pattern.CASE\u不区分大小写);
字符串s=“+1天1月”;
ArrayList结果=新建ArrayList();
Matcher m=RegexCompile.Matcher;
布尔值validFormat=false;
while(m.find()){
如果(m.组(1)=null){
//如果捕获组1(或2或3)为空,则表示第二个
//模式的分支已成功(即\z分支),并且结束
//已达到字符串的长度。
validFormat=真;
}否则{
//否则,这不是字符串的结尾,匹配结果为
//存储在ArrayList“results”中的“temporary”
HashMap结果=新建HashMap();
结果:①m组(1)放置(“符号”);
结果:put(“乘数”,m组(2));
结果:put(“时间单位”,m组(3));
结果。添加(结果);
}
}
if(有效格式){
对于(HashMap项:结果){
System.out.println(“签名:”+item.get(“签名”)
+\n乘数:“+item.get”(“乘数”)
+“\n时间单位:”+item.get(“时间单位”)+“\n”);
}
}否则{
结果:清晰();
System.out.println(“无效格式”);
}

\G
锚点匹配字符串的开头或上一次匹配后的位置。在这种模式中,它确保所有匹配都是连续的。如果到达字符串的结尾,则证明该字符串从头到尾都有效。

Thx,用于回复。你说得对,但我描述得不对。如果我的输入有效,那么我需要为每个匹配提取符号、乘数和时间单位值。使用您的解决方案,它将返回“+1天+1个月”作为1个匹配,而不是两个“+1天”和“+1个月”,您当然可以循环遍历该匹配中的所有组。如果这不能很好地满足您的需要,那么只需多次调用
matcher.find
^\s*([+-]*)(\d+)\s*([a-zA-Z]+)
,每次传入下一个起始索引就可以了。