我在我的正则表达式身体中发现了这些东西,但我不知道我能用它们做什么.有人有例子,所以我可以尝试了解它们是如何工作的吗?
(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind
(?>) - atomic group
Run Code Online (Sandbox Code Playgroud) 这是一系列教育正则表达式文章的第二部分.它显示了向前看符号和嵌套引用如何可以用来匹配非正规languge ñ b ñ.嵌套引用首先介绍在:这个正则表达式如何找到三角形数字?
其中一种原型非常规语言是:
L = { a
ñb
ñ: n > 0 }
这是所有非空字符串的语言,由一些数字a
后跟相同数量的字符串组成b
.在这个语言字符串的例子有ab
,aabb
,aaabbb
.
这种语言可以通过泵浦引理显示为非规则的.它实际上是一种原型上下文无关语言,可以通过无上下文语法 生成S ? aSb | ab
.
尽管如此,现代正则表达式实现清楚地认识到的不仅仅是常规语言.也就是说,它们不是形式语言理论定义的"规则".PCRE和Perl支持递归正则表达式,.NET支持平衡组定义.更少的"花哨"特征,例如反向引用匹配,意味着正则表达式不规则.
但这个"基本"功能有多强大?L
例如,我们可以用Java正则表达式识别吗?我们也许可以结合lookarounds和嵌套引用,并具有与如工作模式String.matches
来匹配字符串一样ab
,aabb
,aaabbb
,等?
java.util.regex.Pattern
现代正则表达式引擎中有一些功能允许您匹配没有该功能时无法匹配的语言.例如,使用后引用的以下正则表达式匹配由重复自身的单词组成的所有字符串的语言:(.+)\1
.此语言不常规,不能与不使用反向引用的正则表达式匹配.
外观是否也会影响正则表达式可以匹配的语言?即是否有任何语言可以使用无法匹配的外观匹配?如果是这样,对于所有类型的环视(负面或正向前瞻或后观)或仅仅针对其中一些而言,这是真的吗?
这是一系列教育正则表达式文章的第三部分.它遵循这个正则表达式如何找到三角形数字?(首先介绍嵌套引用)和如何将^ nb ^ n与Java正则表达式匹配? (前瞻性"计数"机制进一步详述).这部分介绍了一种特定形式的嵌套断言,当与嵌套引用结合使用时,Java正则表达式可以匹配大多数人认为"不可能"的东西:回文!
回文的语言是非常规的 ; 它实际上是无上下文的(对于给定的字母表).也就是说,现代正则表达式实现不仅仅识别常规语言,Perl/PCRE的递归模式和.NET的平衡组可以很容易地识别回文(参见:相关问题).
但是,Java的正则表达式引擎既不支持这些"高级"功能.然而"某人" (*wink*)成功编写了以下正则表达式,这似乎做得很好(参见ideone.com):
public class Palindrome {
// asserts that the entirety of the string matches the given pattern
static String assertEntirety(String pattern) {
return "(?<=(?=^pattern$).*)".replace("pattern", pattern);
}
public static void main(String[] args) {
final String PALINDROME =
"(?x) | (?:(.) add)+ chk"
.replace("add", assertEntirety(".*? (\\1 \\2?)"))
.replace("chk", assertEntirety("\\2"));
System.out.println(PALINDROME);
// (?x) | (?:(.) (?<=(?=^.*? (\1 \2?)$).*))+ (?<=(?=^\2$).*)
String[] tests …
Run Code Online (Sandbox Code Playgroud) 我在C#程序中有以下正则表达式,并且难以理解它:
(?<=#)[^#]+(?=#)
Run Code Online (Sandbox Code Playgroud)
我会把它分解为我认为我理解的内容:
(?<=#) a group, matching a hash. what's `?<=`?
[^#]+ one or more non-hashes (used to achieve non-greediness)
(?=#) another group, matching a hash. what's the `?=`?
Run Code Online (Sandbox Code Playgroud)
所以这个问题我已经是?<=
和?<
组成部分.从阅读MSDN,?<name>
用于命名组,但在这种情况下,尖括号永远不会关闭.
我?=
在文档中找不到,搜索它真的很难,因为搜索引擎大多会忽略那些特殊的字符.
这是一系列教育正则表达式文章的第四部分.它展示了嵌套引用的组合(请参阅:这个正则表达式如何找到三角形数??)在断言中"计数"(参见:我们如何匹配^ nb ^ n与Java正则表达式?)可用于反转字符串.以编程方式生成的模式使用元模式抽象(请参阅:此Java正则表达式如何检测回文?).这是系列中的第一次,这些技术用于替换而不是整个字符串匹配.
提供了完整的Java和C#实现.鼓舞人心的报价包括在内.
使用正则表达式反转字符串似乎不是一个好主意,如果它完全可能,它甚至不会立即显而易见,如果是这样,人们可能会尝试这样做.
虽然它仍然不是一个好主意,但至少现在我们知道这是可能的,因为这是一种方法:
using System;
using System.Text.RegularExpressions;
public class TwoDollarReversal {
public static void Main() {
string REVERSE =
@"(?sx) . grab$2"
.Replace("grab$2",
ForEachDotBehind(
AssertSuffix(@"((.) \1?)")
)
);
Console.WriteLine(
Regex.Replace(
@"nietsniE treblA --
hguone llew ti dnatsrednu t'nod uoy ,ylpmis ti nialpxe t'nac uoy fI",
REVERSE, "$2"
)
);
// If you can't explain it simply, you don't understand it well enough
// -- …
Run Code Online (Sandbox Code Playgroud) 我有以下模式被排除在外.
make it cheaper
make it cheapere
makeitcheaper.com.au
makeitcheaper
making it cheaper
www.make it cheaper
ww.make it cheaper.com
Run Code Online (Sandbox Code Playgroud)
我创建了一个正则表达式以匹配其中任何一个.但是,除了这些之外,我还希望得到其他所有东西.我不知道如何逆转我创建的这个正则表达式.
mak(e|ing) ?it ?cheaper
Run Code Online (Sandbox Code Playgroud)
上面的模式匹配列出的所有字符串.现在我想让它与其他一切相匹配.我该怎么做?
从搜索来看,似乎我需要像负向前瞻/回顾这样的东西.但是,我真的不明白.有人能指出我正确的方向吗?
TL; DR:在.NET的lookbehinds中使用捕获(特别是平衡组)会改变获得的捕获,尽管它不应该有所作为.什么是.NET的外观打破了预期的行为?
我试图找到另一个问题的答案,作为借助.NET平衡组的借口.但是,我不能让他们在可变长度的lookbehind内工作.
首先,请注意我并不打算高效地使用这个特定的解决方案.这更多是出于学术原因,因为我觉得可变长度的lookbehind有一些我不知道的事情.并且知道这可能在将来派上用场,当我真的需要使用这样的东西来解决问题时.
考虑这个输入:
~(a b (c) d (e f (g) h) i) j (k (l (m) n) p) q
Run Code Online (Sandbox Code Playgroud)
我们的目标是匹配所有的字母,这是由前括号内~
,没有多么深跌(所以一切从a
到i
).我的尝试是检查后视镜中的正确位置,以便我可以通过一次调用获得所有字母Matches
.这是我的模式:
(?<=~[(](?:[^()]*|(?<Depth>[(])|(?<-Depth>[)]))*)[a-z]
Run Code Online (Sandbox Code Playgroud)
在lookbehind我尝试找到一个~(
,然后我使用命名组堆栈Depth
来计算无关的开括号.只要打开的括号~(
永远不会关闭,那么lookbehind应该匹配.如果到达(?<-Depth>...)
那个右括号,则无法从堆栈中弹出任何内容,并且lookbehind应该失败(即,对于所有来自的字母j
).不幸的是,这不起作用.相反,我匹配a
,b
,c
,e
,f
,g
和m
.所以只有这些:
~(a b (c) _ (e f (g) _) _) _ (_ (_ (m) _) _) _
Run Code Online (Sandbox Code Playgroud)
这似乎意味着,一旦我关闭了一个单一的括号,看起来就无法匹配任何东西,除非我回到我以前最高的嵌套水平.
好吧,这可能只是意味着我的正则表达式有些奇怪,或者我没有正确理解平衡组.但后来我尝试了这个没有外观.我为每个字母创建了一个字符串,如下所示:
~(z …
Run Code Online (Sandbox Code Playgroud) 最近的许多正则表达式问题在查询中都有某种环视元素,对我来说并不是匹配成功所必需的.是否有一些教学资源正在推广它们?我试图找出哪种情况下你会更好地使用积极的前瞻/后退.我可以看到的主要应用是在尝试不匹配元素时.但是,例如,来自最近问题的这个查询有一个简单的解决方案来捕获.*
,但为什么要使用后面的外观?
(?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span
Run Code Online (Sandbox Code Playgroud)
而这个来自另一个问题:
$url = "www.example.com/id/1234";
preg_match("/\d+(?<=id\/[\d])/",$url,$matches);
Run Code Online (Sandbox Code Playgroud)
什么时候使用积极的环顾四周真的更好?你能举一些例子吗?
我意识到这与基于意见的问题接近,但我认为答案真的很有启发性.正则表达式令人困惑,没有让事情变得更复杂......我已经阅读了这个页面,并且对于何时使用它们而不是它们如何工作的一些简单指南更感兴趣.
感谢所有的答复.除了以下那些,我建议在这里查看m.buettner的好答案.
我一直在谷歌上搜索堆栈溢出提供的推荐问题.但是,我没有找到答案.
我想用正则表达式解析一个字符串,字符串的例子是
Lot: He said: Thou shalt not pass!
我想Lot
作为一个群体捕获,并且He said: Thou shalt not pass!
.但是,当我使用我的(.+): (.+)
模式时,它会返回
Lot: He said:
和 Thou shalt not pass!
是否可以He said: Thou shalt not pass
使用正则表达式捕获?