是什么意思(?!^)

时间:2014-08-01 00:36:34

标签: java regex split

我正在尝试学习正则表达式并感到困惑。 我看到了这篇文章java split () method
所以我对Achintya Jha的第二个答案有一些疑问;

  1. str2.split("");为什么要[, 1, 2, 3]
  2. 是否在文本开头检测到"",如果是,为什么它最后没有检测到相同的内容?
  3. 究竟(?!^)到底是什么意思?
  4. 如果我没有错,a(?!b)如果a后面没有a,则会返回b 并且^找到必须在该行开头匹配的正则表达式,以便(?!^)获得一个空字符串""
    并且^找到必须在该行开头匹配的"" 如果此""后面没有""

    ,则返回""

3 个答案:

答案 0 :(得分:3)

拆分发生在匹配作为参数传递的正则表达式的地方。你需要知道,如果分裂发生,一件事就变成了两件事。总是。没有例外。

您可以怀疑它,因为实例"abc".split("c")返回带有一个元素["ab"]的数组,但这是因为此版本的split在返回之前还会自动从数组中删除尾随的空字符串。

换句话说"abc".split("c")

  1. 创建["ab",""]数组(是的,有空字符串,这是在"abc"上拆分c的结果),
  2. 删除尾随空字符串
  3. 返回结果数组,最后没有那些空字符串,所以它现在返回["ab"]
  4. 另一个例子是在"abc"上拆分"a"。由于a在开始时出现,您将获得["", "bc"]

    但是拆分空字符串有点棘手,因为空字符串在每个字符之前和之后。我将使用管道|标记它们。

    "abc"这些位置"|a|b|c|"中可以找到空"abc"中的空字符串,这意味着当您""["", "a", "b", "c", ""]分开时,<{1}}

    • 此方法(首先)生成数组"abc".split("")
    • 以后删除尾随空字符串

    这就是["", "a", "b", "c"]作为结果数组"|a|b|c|" 返回的原因(这应该回答你的问题1)。

    但是如果我们想要防止第一个空字符串(开头的那个)被split方法匹配怎么办?换句话说,如果我们不想拆分

    ,该怎么办?
     "a|b|c|"
    

    但仅限于

    a|

    我们可以通过几种方式实现这一目标。

    1. 我们可以尝试创建正则表达式,这些正则表达式将匹配这些具有任何字符的whatspace,例如b| c| ""
    2. 我们也可以说我们想要拆分那些没有字符串开头的whatspace。
    3. 要创建此类正则表达式,我们需要look-around个机制。

        • 说空Stirng只需使用(?<=.)
        • 要说某些东西需要在它之前有其他东西,我们可以使用正面观察"(?<=.)"

        如果我们将以前的两个品脱结合起来:"""(?<=.)"+"",我们会得"(?<=.)" "abc".split("(?<=.)"),因此.只能在这些空以任何字符开头的字符串(以点(?<!...)表示的正则表达式)。

      1. 要说某些内容不能停留在字符串的开头,我们可以使用负面观察^(?<!^)来表示字符串的开头。所以"(?<!^)表示条件&#34;在它之前没有字符串的开头&#34;。这就是为什么 ↓ "|a|b|c|" 无法匹配此空格

        的原因
        (?!^)
      2. 因为它之前有字符串的开头。

        实际上还有一个特殊情况是你的问题的主要观点^,这意味着负向前瞻。这个正则表达式描述了空字符串,后面没有字符串的开头。它有点不直观,因为之前我们假设字符串的开头(由 ↓ "^|a|b|c|" 表示)放在这里

          ↓
        "|^a|b|c|"
        

        但现在它看起来像是在这里:

         ↓
        "^abc"
        

        那是怎么回事?它是如何工作的?
        正如我之前所说,拆分空字符串很棘手。要理解这一点,你需要看看没有标记空字符串的字符串,你会看到字符串的开头就在这里

        "a"

        换句话说,正则表达式也考虑在第一个字符(在我们的例子中为 ↓ "|^a|b|c|" )之前的位置作为其开头,所以

        (?!^)

        也有意义且有效,这就是 ↓ "|^a|b|c|" 能够看到这个空字符串

        的原因
        (?<=.)

        在字符串开始之前,并且不接受它作为有效的分割位置。


        无论如何,由于这对于不熟悉正则表达式的开发人员造成了混淆,因此从Java 8开始,我们不必使用(?<!^)(?!^)split的技巧避免在开头创建空字符串,因为如本问题所述

        Why in Java 8 split sometimes removes empty strings at start of result array?

        它会在生成的数组的开头自动删除空字符串,因为"abc".split("")中使用的长正则表达式代表zero-length字符串(如空字符串),因此您现在可以使用["a", "b", "c"]和得到结果{{1}}。

答案 1 :(得分:2)

  

(1)为什么str2.split("");[, 1, 2, 3] (2)的形式发出?它是否在文本开头检测到"",如果是,为什么它不执行最后一样吗?`

通过拆分空字符串,它将返回空字符串作为第一项。如果您正在搜索的字符串中没有定义分隔符,您将获得一个大小为1的数组,即使该字符串为空,它也会保留原始字符串。


  

(3) (?!^)究竟是什么意思?

这是一个Negative Lookahead断言,断言它不位于字符串开头之前/之后。

(?!   # look ahead to see if there is not:
  ^   #   the beginning of the string
)     # end of look-ahead

你对Negative Lookahead的工作原理是正确的。

a(?!b) # matches a when not followed by b

答案 2 :(得分:1)

正则表达式:

(?!^)

输入开始是负面展望。这意味着&#34;没有在输入开始之前定位&#34;。

因为否则空白的正则表达式在开始之前匹配,这个断言会阻止它在那里分裂,所以它只在字符之间分开(不在开始和第一个字符之间)。

实现同样目标的另一个正则表达式是:

(?<=.)

对于任何角色来说都是一个背后的东西,即&#34;在任何角色之后#34;我觉得更清楚。