是什么意思(?!^)
我正在尝试学习正则表达式并感到困惑。 我看到了这篇文章的java split()方法
所以我对Achintya Jha的第二个答案有些疑问;
- 为什么
str2.split("");
给出[, 1, 2, 3]
- 它是否在文本开头检测到
""
,如果是,为什么它最后不会这样做? - 究竟是什么
(?!^)
意思?
如果我没有错a(?!b)
返回a
如果a后面没有b
和^
找到必须在行开头匹配的正则表达式,因此(?!^)
获取一个空字符串""
和^
找到必须在该行的开头匹配的""
如果此""
后面没有""
则返回""
?
拆分发生在匹配作为参数传递的正则表达式的地方。 你需要知道,如果分裂发生,一件事就变成了两件事。 总是。 没有例外。
您可以怀疑它,因为实例"abc".split("c")
返回带有一个元素["ab"]
数组,但这是因为此版本的split
在返回之前还会自动从数组中删除尾随空字符串。
换句话说"abc".split("c")
- 创建
["ab",""]
数组(是的,有空字符串,这是c
上拆分"abc"
结果), - 删除尾随空字符串
- 返回结果数组,结尾没有那些空字符串,所以现在返回
["ab"]
另一个例子是在"a"
上拆分"abc"
"a"
。 由于a
在开始时出现,你将获得["", "bc"]
。
但是拆分空字符串有点棘手,因为空字符串在每个字符之前和之后。 我将用管道标记它们 。
所以"abc"
空字符串可以在这些位置找到"|a|b|c|"
这意味着当你在""
上拆分"abc"
时
- 这个方法(首先)产生数组
["", "a", "b", "c", ""]
- 然后删除尾随的空字符串
这就是为什么"abc".split("")
返回结果数组["", "a", "b", "c"]
(这应该回答你的问题1)。
但是如果我们想要防止第一个空字符串(开始时的那个)被split方法匹配呢? 换句话说,如果我们不想拆分怎么办?
"|a|b|c|"
但只有
"a|b|c|"
我们可以通过几种方式做到这一点。
- 我们可以尝试创建正则表达式,它将匹配这些具有任何字符的whatspace,就像
a|
b|
c|
。 - 我们还可以说我们想要拆分在它们之前没有字符串开头的whatspace。
要创建这样的正则表达式,我们需要环视机制。
-
- 说空Stirng只是用
""
- 要说某些东西需要在它之前有其他东西我们可以使用正面观察
(?<=.)
。
如果我们将前两个品脱结合起来:
"(?<=.)"
和""
我们将得到"(?<=.)"+""
这就是"(?<=.)"
所以"abc".split("(?<=.)")
应仅在这些前面带有任何字符的空字符串上拆分(在由dot表示的正则表达式中)。 - 说空Stirng只是用
-
要说某些东西不能停留在字符串的开头,我们可以使用负后视
(?和
^
来表示字符串的开头。 所以(?表示条件“在它之前没有字符串的开头”。 这就是
"(?无法匹配此空白区域的原因
↓ "|a|b|c|"
因为它之前有字符串的开头。
实际上还有一个特殊情况是你的问题的主要观点(?!^)
,这意味着负向前瞻。 这个正则表达式描述了空字符串,后面没有字符串的开头。 它有点不直观,因为之前我们假设字符串的开头(由^
表示)放在这里
↓ "^|a|b|c|"
但现在它看起来像是在这里:
↓ "|^a|b|c|"
那么发生了什么? 它是如何工作的?
正如我之前所说,拆分空字符串很棘手。 要理解这一点,你需要看一下没有标记空字符串的字符串,你会看到字符串的开头就在这里
↓ "^abc"
换句话说,正则表达式也考虑在第一个字符(在我们的例子中为"a"
)之前的位置作为它的开始,所以
↓ "|^a|b|c|"
使得也有意义并且有效,这就是为什么(?!^)
能够看到这个空字符串的原因
↓ "|^a|b|c|"
正好在字符串开始之前,并且不会将其作为有效的分割地点。
无论如何,由于这对于不熟悉正则表达式的开发人员造成混淆,从Java 8开始,我们不必使用技巧(?<=.)
或(?或
(?!^)
来避免创建开头的空字符串,因为如此问题所述
为什么在Java 8 split中有时会在结果数组的开头删除空字符串?
它会在生成数组的开头自动删除空字符串,因为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
你对Negative Lookahead的工作原理是正确的。
a(?!b) # matches a when not followed by b
正则表达式:
(?!^)
对于输入的开始是负面outlook。 这意味着“在输入开始之前没有定位”。
因为否则空白的正则表达式在开始之前匹配,这个断言会阻止它在那里分裂,因此它只在字符之间分割(不在开始和第一个字符之间)。
实现同样目标的另一个正则表达式是:
(?<=.)
这是任何角色的背后,即“在任何角色之后”,我觉得更清楚。