【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
是否可以使用另一个正则表达式检测有效的正则表达式? 如果是这样,请在下面举例说明。
#1楼
不太可能。
在try..catch
或您提供的语言中评估它。
#2楼
/
^ # start of string
( # first group start
(?:
(?:[^?+*{}()[\]\\|]+ # literals and ^, $
| \\. # escaped characters
| \[ (?: \^?\\. | \^[^\\] | [^\\^] ) # character classes
(?: [^\]\\]+ | \\. )* \]
| \( (?:\?[:=!]|\?<[=!]|\?>)? (?1)?? \) # parenthesis, with recursive content
| \(\? (?:R|[+-]?\d+) \) # recursive matching
)
(?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )? # quantifiers
| \| # alternative
)* # repeat content
) # end first group
$ # end of string
/
这是一个递归正则表达式,许多正则表达式引擎都不支持。 基于PCRE的应该支持它。
没有空格和评论:
/^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/
.NET不直接支持递归。 ( (?1)
和(?R)
构造。)递归必须转换为计数平衡组:
^ # start of string
(?:
(?: [^?+*{}()[\]\\|]+ # literals and ^, $
| \\. # escaped characters
| \[ (?: \^?\\. | \^[^\\] | [^\\^] ) # character classes
(?: [^\]\\]+ | \\. )* \]
| \( (?:\?[:=!]
| \?<[=!]
| \?>
| \?<[^\W\d]\w*>
| \?'[^\W\d]\w*'
)? # opening of group
(?<N>) # increment counter
| \) # closing of group
(?<-N>) # decrement counter
)
(?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )? # quantifiers
| \| # alternative
)* # repeat content
$ # end of string
(?(N)(?!)) # fail if counter is non-zero.
压实:
^(?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>|\?<[^\W\d]\w*>|\?'[^\W\d]\w*')?(?<N>)|\)(?<-N>))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*$(?(N)(?!))
来自评论:
这会验证替换和翻译吗?
它将仅验证替代和翻译的正则表达式部分。 s/<this part>/.../
理论上不可能将所有有效的正则表达式语法与正则表达式匹配。
如果正则表达式引擎支持递归(例如PCRE),但实际上不能再称为正则表达式。
实际上,“递归正则表达式”不是正则表达式。 但这是一个经常被接受的正则表达式引擎的扩展......具有讽刺意味的是,这个扩展的正则表达式与扩展的正则表达式不匹配。
“理论上,理论和实践都是一样的。在实践中,它们不是。” 几乎每个知道正则表达式的人都知道正则表达式不支持递归。 但PCRE和大多数其他实现支持的不仅仅是基本的正则表达式。
在grep命令中使用它与shell脚本,它显示了一些错误.. grep:{}的内容无效。 你能帮忙吗,我正在创建一个脚本,可以grep一个代码库来查找包含正则表达式的所有文件
此模式利用称为递归正则表达式的扩展。 正则表达式的POSIX风格不支持此功能。 您可以尝试使用-P开关,以启用PCRE正则表达式风格。
正则表达式本身“不是常规语言,因此无法通过正则表达式进行解析...”
对于经典正则表达式,这是正确的。 一些现代实现允许递归,这使得它成为一种Context Free语言,尽管这个任务有点冗长。
我看到你匹配
[]()/\\
。 和其他特殊的正则表达式字符。 你在哪里允许非特殊字符? 看起来这将匹配^(?:[\\.]+)$
,但不匹配^abcdefg$
。 这是一个有效的正则表达式。
[^?+*{}()[\\]\\\\|]
将匹配任何单个字符,而不是任何其他结构的一部分。 这包括文字( a
- z
)和某些特殊字符( ^
, $
, .
)。
#3楼
好问题。 真正的常规语言无法决定任意深度嵌套的良好形式的括号。 即,如果您的字母包含'('和')',那么目标是确定这些字符串是否具有格式良好的匹配括号。 由于这是正则表达式的必要条件,因此答案是否定的。
但是:如果放宽要求并添加递归,则可以执行此操作。 原因是递归可以充当“堆栈”,让您通过推入此堆栈来“计算”当前的嵌套深度。
Russ Cox撰写了一篇关于正则表达式引擎实现的精彩论文: 正则表达式匹配可以简单快速
#4楼
如果你严格地谈论正则表达式而不包括一些实际上是无上下文语法的正则表达式实现,那就不。
正则表达式有一个限制,这使得无法编写匹配所有正则表达式的正则表达式。 您无法匹配配对的大括号等实现。 正则表达式使用许多这样的结构,让我们以[]为例。 只要有[必须有匹配]。 足够简单的正则表达式“[。*]”。
正则表达式无法实现的原因是它们可以嵌套。 你怎么写一个匹配嵌套括号的正则表达式? 答案是你不能没有无限长的正则表达式。 你可以通过暴力匹配任意数量的嵌套parens,但你不能匹配任意长的嵌套括号。
此功能通常称为计数(您计算嵌套的深度)。 根据定义,正则表达式无法计数。
编辑:结束撰写关于此的博客文章: 正则表达式限制
#5楼
虽然完全有可能像MizardX发布的那样使用递归正则表达式,但对于这类事情来说,解析器更有用。 Regexes最初打算用于常规语言,递归或平衡组只是一个补丁。
定义有效正则表达式的语言实际上是一个无上下文语法,您应该使用适当的解析器来处理它。 这是一个用于解析简单正则表达式的大学项目的示例(没有大多数构造)。 它使用JavaCC。 是的,评论是西班牙语,虽然方法名称是不言自明的。
SKIP :
{
" "
| "\r"
| "\t"
| "\n"
}
TOKEN :
{
< DIGITO: ["0" - "9"] >
| < MAYUSCULA: ["A" - "Z"] >
| < MINUSCULA: ["a" - "z"] >
| < LAMBDA: "LAMBDA" >
| < VACIO: "VACIO" >
}
IRegularExpression Expression() :
{
IRegularExpression r;
}
{
r=Alternation() { return r; }
}
// Matchea disyunciones: ER | ER
IRegularExpression Alternation() :
{
IRegularExpression r1 = null, r2 = null;
}
{
r1=Concatenation() ( "|" r2=Alternation() )?
{
if (r2 == null) {
return r1;
} else {
return createAlternation(r1,r2);
}
}
}
// Matchea concatenaciones: ER.ER
IRegularExpression Concatenation() :
{
IRegularExpression r1 = null, r2 = null;
}
{
r1=Repetition() ( "." r2=Repetition() { r1 = createConcatenation(r1,r2); } )*
{ return r1; }
}
// Matchea repeticiones: ER*
IRegularExpression Repetition() :
{
IRegularExpression r;
}
{
r=Atom() ( "*" { r = createRepetition(r); } )*
{ return r; }
}
// Matchea regex atomicas: (ER), Terminal, Vacio, Lambda
IRegularExpression Atom() :
{
String t;
IRegularExpression r;
}
{
( "(" r=Expression() ")" {return r;})
| t=Terminal() { return createTerminal(t); }
| <LAMBDA> { return createLambda(); }
| <VACIO> { return createEmpty(); }
}
// Matchea un terminal (digito o minuscula) y devuelve su valor
String Terminal() :
{
Token t;
}
{
( t=<DIGITO> | t=<MINUSCULA> ) { return t.image; }
}
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3143917