我正在尝试学习正则表达式并感到困惑。我看到了这个帖子java拆分((方法
所以我对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
在开始时存在,因此您将获得["", "bc"]
。
但是在空字符串上拆分有点棘手,因为空字符串在每个字符之前和之后。我将使用管道|
标记它们。
因此,可以在这些位置找到"abc"
中的空字符串"|a|b|c|"
这意味着当您在""
上拆分"abc"
时
- 此方法(起初(生成数组
["", "a", "b", "c", ""]
- 稍后删除尾随空字符串
这就是为什么"abc".split("")
返回结果数组["", "a", "b", "c"]
(这应该回答你的问题 1(。
但是,如果我们想防止第一个空字符串(开始时的那个(被拆分方法匹配怎么办?换句话说,如果我们不想分裂怎么办
"|a|b|c|"
但仅在
"a|b|c|"
我们可以通过几种方式做到这一点。
- 我们可以尝试创建正则表达式,它将匹配这些在它们之前具有任何字符的 whatspace
a|
b|
c|
. - 我们也可以说,我们想拆分前面没有字符串开头的空间。
要创建这样的正则表达式,我们需要环顾机制。
- 要说空的斯特恩就用
""
- 要说某事需要有别的东西才能有它,我们可以使用 积极的后视
(?<=.)
.
如果我们结合前两个品脱:
"(?<=.)"
和""
我们将得到"(?<=.)"+""
它只是"(?<=.)"
所以"abc".split("(?<=.)")
应该只在这些空字符串上拆分,这些空字符串前面有任何字符(在正则表达式中由点.
表示(。- 要说空的斯特恩就用
要说某些东西不能停留在字符串的开头,我们可以使用负后看
(?<!...)
和^
来表示字符串的开头。所以(?<!^)
表示条件"之前没有字符串开头"。这就是为什么"(?<!^)
无法匹配这个空白↓ "|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
正则表达式:
(?!^)
是输入开始的负面展望。它的意思是"在输入开始之前未定位"。
由于原本空白的正则表达式在开始之前匹配,因此此断言会停止它在那里拆分,因此它仅在字符之间拆分(而不是在开始和第一个字符之间(。
实现相同目标的另一个正则表达式是:
(?<=.)
这是任何角色的背后看,即"在任何角色之后",我觉得更清楚。