Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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 使用正则表达式拆分字符串\w\w*\w+;?_Java_Regex - Fatal编程技术网

Java 使用正则表达式拆分字符串\w\w*\w+;?

Java 使用正则表达式拆分字符串\w\w*\w+;?,java,regex,Java,Regex,我正在学习regexp,我想我已经开始掌握了。但是 我试图拆分一个字符串,我需要帮助来理解这样一个简单的事情: String input = "abcde"; System.out.println("[a-z] " + Arrays.toString(input.split("[a-z]"))); System.out.println("\\w " + Arrays.toString(input.split("\\w"))); System.out.println("\\w*? " + Arra

我正在学习regexp,我想我已经开始掌握了。但是

我试图拆分一个字符串,我需要帮助来理解这样一个简单的事情:

String input = "abcde";
System.out.println("[a-z] " + Arrays.toString(input.split("[a-z]")));
System.out.println("\\w " + Arrays.toString(input.split("\\w")));
System.out.println("\\w*? " + Arrays.toString(input.split("\\w*?")));
System.out.println("\\w+? " + Arrays.toString(input.split("\\w+?")));

The output is
[a-z] - []
\w    - []
\w*?  - [, a, b, c, d, e]
\w+?  - []
为什么前两行中的任何一行都不拆分任何字符上的字符串? 第三个表达式\w*?,(问号防止贪婪)如我所料工作,在每个字符上拆分字符串。零个或多个匹配的星号返回空数组

我在记事本++和一个程序中尝试过该表达式,它显示了5个匹配项,如中所示:

Scanner ls = new Scanner(input);
while(ls.hasNext())
    System.out.format("%s ", ls.findInLine("\\w");

Output is: a b c d e

这真的让我很困惑

如果你用正则表达式分割一个字符串,你基本上就知道应该在哪里剪切字符串。这必然会删除与正则表达式匹配的内容。这意味着如果在
\w
处拆分,则每个字符都是拆分点,并且返回它们之间的子字符串(全部为空)。Java会自动删除尾随的空字符串,如中所述

这也解释了为什么惰性匹配
\w*?
将为您提供每个字符,因为它将匹配任何字符(零宽度)之间(以及之前和之后)的每个位置。剩下的是字符串本身的字符

让我们把它分解一下:

  • [a-z]
    \w
    \w+?

      a  b  c  d  e
    └┘ └┘ └┘ └┘ └┘ └┘
    
    你的绳子是

    abcde
    
    比赛内容如下:

     a  b  c  d  e
    └─┘└─┘└─┘└─┘└─┘
    
    这会在匹配之间留下子字符串,所有子字符串都是空的

    上述三个正则表达式在这方面的行为相同,因为它们都只匹配一个字符
    \w+?
    将这样做,因为它缺少任何其他约束,这些约束可能会使
    +?
    尝试匹配的不仅仅是简单的最小值(毕竟它是懒惰的)

  • \w*?

      a  b  c  d  e
    └┘ └┘ └┘ └┘ └┘ └┘
    
    在这种情况下,匹配在字符之间,留下以下子字符串:

    "", "a", "b", "c", "d", "e", ""
    
    不过,Java将后面的空文件扔掉了

  • 在模式的每个匹配处剪切字符串:

    此方法返回的数组包含此字符串的每个子字符串,该子字符串由与给定表达式匹配的另一个子字符串终止,或由字符串结尾终止

    因此,无论何时匹配像
    [a-z]
    这样的模式,字符串都会在该匹配处剪切。由于字符串中的每个字符都与模式匹配,因此生成的数组为空(删除尾随的空字符串)


    这同样适用于
    \w
    \w+?
    (一个或多个
    \w
    ,但重复次数尽可能少)。
    \w*?
    产生了您所期望的结果,这是由于
    *?
    量词可能会匹配零重复,因此为空字符串。在给定字符串的每个位置都会找到一个空字符串。

    让我们将这些调用分解为。关键是要从Java文档中注意到,“方法的工作方式就像使用给定的表达式和零的limit参数调用一样。因此,结果数组中不包括尾随的空字符串。”

    这一个匹配每个字符(a、b、c、d、e),并且只在它们之间产生空字符串,这些字符串被省略

    "abcde".split("\\w")); // => []
    
    "abcde".split("\\w*?")); // => ["", "a", "b", "c", "d", "e"]
    
    同样,字符串中的每个字符都是单词字符(
    \w
    ),因此结果是空字符串,这些字符串将被忽略

    "abcde".split("\\w")); // => []
    
    "abcde".split("\\w*?")); // => ["", "a", "b", "c", "d", "e"]
    
    在这种情况下,
    *
    表示“前面的项为零或多个”(
    \w
    ),它与空表达式匹配七次(一次在字符串开头,然后在每个字符之间匹配一次)。所以我们得到第一个空字符串,然后是每个字符

    "abcde".split("\\w+?")); // => []
    
    这里的
    +
    表示“前面的一个或多个项”(
    \w
    ),它与整个输入字符串相匹配,只产生空字符串,该字符串被省略


    使用
    input.split(regex,-1)
    再次尝试这些示例,您应该会看到所有的空字符串。

    我也想接受您的答案,谢谢您的帮助@肯尼特:当然,请考虑一下你认为有帮助的答案。我不敢相信你用java来分配ReGEX作业,而不是用不需要\\Dou\\O\\Uu \ BB\\\\\B\\A\\Acc\cc\\k\\\\\AA\\\\\\H\\HH\EE!!多痛苦啊!此外,您甚至不需要对正则表达式语法进行编译时检查,也不需要调试,等等。Java对这种工作不是很方便。您应该用一种更具同情心的语言开发正则表达式,然后将最终结果转换为Java。@tchrist您在考虑什么语言?除了sed和awk等shell工具外,Perl和Ruby还有一流的正则表达式,甚至Python也允许您跳过双反斜杠。Perl是唯一一个使用正则表达式调试器的调试器。Java的
    split
    丢弃了后面的空字段,因为它模仿了Perl的
    split
    ,后者就是这样做的。在这两种语言中,您都可以通过向
    -1
    拆分添加另一个参数来抑制该行为。