What is the meaning of (?!^)



我正在尝试学习正则表达式并感到困惑。我看到了这个帖子java拆分((方法
所以我对Achintya Jha的第二个答案有一些疑问;

  1. 为什么str2.split("");会给出[, 1, 2, 3]
  2. 它是否在文本开头检测到"",如果是,为什么在结尾不做同样的事情?
  3. (?!^)到底是什么意思?

如果我没有记错a(?!b)则返回a如果 a 后面没有b
^找到必须在行首匹配的正则表达式,因此(?!^)得到一个空字符串""
^找到必须在行首匹配的""所以如果这个""后面没有"",则返回""

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

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

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

  1. 创建["ab",""]数组(是的,有空字符串,这是在c上拆分"abc"的结果(,
  2. 删除尾随空字符串
  3. 返回
  4. 结果数组,末尾没有那些空字符串,所以现在它返回["ab"]

另一个例子是在"a"上拆分"abc"。由于a在开始时存在,因此您将获得["", "bc"]

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

因此,可以在这些位置找到"abc"中的空字符串"|a|b|c|"这意味着当您在""上拆分"abc"

  • 此方法(起初(生成数组["", "a", "b", "c", ""]
  • 稍后删除尾随空字符串

这就是为什么"abc".split("")返回结果数组["", "a", "b", "c"](这应该回答你的问题 1(。

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

"|a|b|c|"

但仅在

 "a|b|c|"

我们可以通过几种方式做到这一点。

  1. 我们可以尝试创建正则表达式,它将匹配这些在它们之前具有任何字符的 whatspace a| b| c| .
  2. 我们也可以说,我们想拆分前面没有字符串开头的空间。

要创建这样的正则表达式,我们需要环顾机制。

    • 要说空的斯特恩就用""
    • 要说某事需要有别的东西才能有它,我们可以使用 积极的后视(?<=.) .

    如果我们结合前两个品脱:"(?<=.)""" 我们将得到"(?<=.)"+""它只是"(?<=.)"所以"abc".split("(?<=.)")应该只在这些空字符串上拆分,这些空字符串前面有任何字符(在正则表达式中由点 . 表示(。

  1. 要说某些东西不能停留在字符串的开头,我们可以使用负后看(?<!...)^来表示字符串的开头。所以(?<!^)表示条件"之前没有字符串开头"。这就是为什么"(?<!^)无法匹配这个空白

     ↓  
    "|a|b|c|"
    

因为它前面有字符串的开头。

实际上,还有一个特例是你问题的主要观点(?!^)这意味着消极的展望。此正则表达式描述空字符串,该字符串后面没有字符串的开头。这有点不直观,因为之前我们假设字符串的开头(用 ^ 表示(放在这里

 ↓
"^|a|b|c|"

但现在看起来它在这里:

  ↓
"|^a|b|c|"

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

 ↓
"^abc"

换句话说,正则表达式还认为第一个字符(在我们的例子中是"a"(之前的位置作为它的开始,所以

  ↓
"|^a|b|c|"

也很有意义并且有效,这就是为什么(?!^)能够看到这个空字符串的原因

 ↓
"|^a|b|c|"

就像字符串开始之前一样,并且不会接受它作为拆分的有效位置。


无论如何,由于这给不太熟悉正则表达式的开发人员带来了困惑,因此从Java 8开始,我们不必使用(?<=.)(?<!^)(?!^)的技巧来避免在开始时创建空字符串,因为如本问题所述

为什么在 Java 8 中,拆分有时会在结果数组的开头删除空字符串?

它在生成的数组开始时自动删除空字符串,因为 split 中使用的正则表达式表示零长度字符串(如空字符串(,因此您现在可以使用 "abc".split("") 并获取结果["a", "b", "c"]

(1) 为什么str2.split("");在文本开头[, 1, 2, 3] (2)它是否检测到"",如果是,为什么它在结尾不做同样的事情?">

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


(3) (?!^)到底是什么意思?

这是一个否定前瞻断言,它断言它没有定位在字符串的开头/开头。

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

你对消极展望的工作原理是正确的。

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

正则表达式:

(?!^)

是输入开始的负面展望。它的意思是"在输入开始之前未定位"。

由于原本空白的正则表达式在开始之前匹配,因此此断言会停止它在那里拆分,因此它仅在字符之间拆分(而不是在开始和第一个字符之间(。

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

(?<=.)

这是任何角色的背后看,即"在任何角色之后",我觉得更清楚。

相关内容

最新更新