尝试编译以下正则表达式时,我收到PatternSyntaxException:
"bd".matches("(a)?b(?(1)c|d)")
Run Code Online (Sandbox Code Playgroud)
这个正则表达式匹配bd和abc.它与bc不匹配.
有任何想法吗?谢谢.
好吧,我需要写正则表达式来匹配接下来的4个字符串:
*date date* date date1*date2
Run Code Online (Sandbox Code Playgroud)
不应该匹配:
*date* date1*date2* *date1*date2 date** ...
Run Code Online (Sandbox Code Playgroud)
但这应该通过单一匹配来完成,而不是几个.
请不要发布如下答案:
(date*date)|(*date)|(date*)|(date)
Run Code Online (Sandbox Code Playgroud)
想象一下,如果你能使用一种缺乏else陈述的语言,但你想模仿它.而不是写作
if (condition) { yes part }
else { no part }
Run Code Online (Sandbox Code Playgroud)
你必须写
if (condition) { yes part }
if (!condition) { no part }
Run Code Online (Sandbox Code Playgroud)
嗯,这就是你必须要做的,但在模式中.你在没有条件的Java中做的是你在ELSE块中重复条件,但是否定它,它实际上是一个OR块.
因此,例如,而不是像Perl这样的语言在模式中使用条件支持来编写它:
# definition of \b using a conditional in the pattern like Perl
#
(?(?<= \w) # if there is a word character to the left
(?! \w) # then there must be no word character to the right
| (?= \w) # else there must be a word character to the right
)
Run Code Online (Sandbox Code Playgroud)
你必须在Java中写道:
# definition of \b using a duplicated condition like Java
#
(?: (?<= \w) # if there is a word character to the left
(?! \w) # then there must be no word character to the right
| # ...otherwise...
(?<! \w) # if there is no word character to the left
(?= \w) # then there must be a word character to the right
)
Run Code Online (Sandbox Code Playgroud)
您可能会认识到这是定义\b.在这里,同样\B的定义,首先使用条件:
# definition of \B using a conditional in the pattern like Perl
#
(?(?<= \w) # if there is a word character to the left
(?= \w) # then there must be a word character to the right
| (?! \w) # else there must be no word character to the right
)
Run Code Online (Sandbox Code Playgroud)
现在通过重复OR分支中的(现在否定的)条件:
# definition of \B using a duplicated condition like Java
#
(?: (?<= \w) # if there is a word character to the left
(?! \w) # then there must be no word character to the right
| # ...otherwise...
(?<! \w) # if there is no word character to the left
(?= \w) # then there must be a word character to the right
)
Run Code Online (Sandbox Code Playgroud)
请注意如何,无论你如何把它们卷,即各自的定义\b和\B喜爱的责任完全在的定义\w,从来没有上\W,更别说上\s.
能够使用条件不仅可以节省打字,还可以减少错误的机会.它们也可能是您不关心两次评估病情的情况.
在这里,我利用它来定义几个正则表达式子程序,它们为我提供了一个希腊语原子和相同的边界:
(?(DEFINE)
(?<greeklish> [\p{Greek}\p{Inherited}] )
(?<ungreeklish> [^\p{Greek}\p{Inherited}] )
(?<greek_boundary>
(?(?<= (?&greeklish))
(?! (?&greeklish))
| (?= (?&greeklish))
)
)
(?<greek_nonboundary>
(?(?<= (?&greeklish))
(?= (?&greeklish))
| (?! (?&greeklish))
)
)
)
Run Code Online (Sandbox Code Playgroud)
请注意边界和非边界如何仅使用(&?greeklish),从不(?&ungreeklish)?你永远不需要做任何只做边界的事情.你把没有进入你的lookarounds代替,就像\b和\B都这样做.
虽然在Perl中,定义一个新的自定义属性\p{IsGreeklish}(以及它的补充\P{IsGreeklish})可能更容易(尽管不那么通用):
sub IsGreeklish {
return <<'END';
+utf8::IsGreek
+utf8::IsInherited
END
}
Run Code Online (Sandbox Code Playgroud)
虽然不是因为Java缺乏对条件的支持,但是因为它的模式语言不允许(DEFINE)块或正则表达式的子程序调用(?&greeklish)- 实际上,你的模式,你将无法将其中的任何一个转换为Java.甚至无法用Java进行递归.您也不能在Java中定义自定义属性\p{IsGreeklish}.
当然,Perl正则表达式中的条件可能不仅仅是外观:它们甚至可以是代码块来执行 - 这就是为什么你当然不希望被迫两次评估相同的条件,以免它产生副作用.这不适用于Java,因为它无法做到这一点.你不能混合使用模式和代码,这比你习惯这样做之前想象的要多.
你可以用Perl正则表达式引擎做很多事情,你可以用别的语言来做,这只是其中的一部分.毫无疑问,新编程Perl的第4版中大大扩展的Regexes章节,加上完全重写的Unicode章节,现在紧跟Regexes章节(已被提升为内核的一部分),具有组合页面数量类似于130页的内容,因此从第3版开始,模式匹配的旧章节的长度增加了一倍.
您刚才看到的是新版第4版的一部分,应该会在下个月左右出版.
小智 2
根据OP的编辑和示例添加新答案:
ok i need to write regex to match next 4 strings:
*date date* date date1*date2
should not match:
*date* date1*date2* *date1*date2 date** ...
如果我想我理解你的意思,你可以使用基于 Alan Moore 伪条件技巧的正则表达式。
像这样的东西^(?:[*]())?date(?:(?!\1)[*](?:date)?|)$可能会起作用。
我假设“日期”是示例中的唯一文本,并且示例中的每组非空格字符都是不同的文本行。
在您传递的文本中,只有一种形式需要伪条件。那就是“日期*日期”。因此,为了清楚起见,我在下面提供了一个 Perl 示例(因为我没有 Java 编译器),它扩展了正则表达式。
use strict;
use warnings;
my @samps = qw(
*date
date*
date
date*date
*date*
date*date*
*date*date
date**
);
for my $str (@samps)
{
print "\n'$str'\n";
if ($str =~
/
^ # Begin of string
(?: # Expr grouping
[*]() # Asterisk found then DEFINE capture group 1 as empty string
)? # End expr group, optional, if asterisk NOT found, capture group 1 stays UNDEFined
date # 'data'
(?: # Expr grouping
(?!\1) # Pseudo conditional: If no asterisk (group 1 is UNDEF), then
[*](?:date)? # look for '*' folowed by optional 'data'
| # OR,
) # Asterisk or not, should be nothing here
$ # End of string
/x)
{
print "matched: '$str'\n";
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
'*date'
matched: '*date'
'date*'
matched: 'date*'
'date'
matched: 'date'
'date*date'
matched: 'date*date'
'*date*'
'date*date*'
'*date*date'
'date**'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4030 次 |
| 最近记录: |