- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
尽管我对伪代码中的正则表达式有足够的了解,但是我仍然无法翻译我想在php regex perl中执行的操作。
我正在尝试使用preg_match提取表达式的一部分。
我有以下字符串${classA.methodA.methodB(classB.methodC(classB.methodD)))}
,我需要做2件事:
一种。验证语法
${classA.methodA.methodB(classB.methodC(classB.methodD)))}
有效 ${classA.methodA.methodB}
有效 ${classA.methodA.methodB()}
无效 ${methodB(methodC(classB.methodD)))}
无效 ${classA.methodA.methodB(classB.methodC(classB.methodD)))}
应该返回
$expression = '${myvalue.fdsfs.fsdf.blo(fsdf.fsfds(fsfs.fs))}';
$pattern = '/\$\{(?:([a-zA-Z0-9]+)\.)(?:([a-zA-Z\d]+)\.)*([a-zA-Z\d.()]+)\}/';
if(preg_match($pattern, $expression, $matches))
{
echo 'found'.'<br/>';
for($i = 0; $i < count($matches); $i++)
echo $i." ".$matches[$i].'<br/>';
}
$expression = '${myvalue.fdsfs}';
found
0 ${myvalue.fdsfs}
1 myvalue.fdsfs
2 myvalue
3
4 fdsfs
$expression = '${classA.methodAA(classB.methodBA(classC.methodCA),classC.methodCB)}';
$expression = '${classA.methodAA(classB.methodBA(classC.methodCA),classC.methodCB,classD.mehtodDA)}';
$expressionPattern =
'/
^ # beginning of the string
[$][{] # literal ${
( # group 1, used for recursion
( # group 2 (class name)
[a-z\d]+ # one or more alphanumeric characters
) # end of group 2 (class name)
[.] # literal .
( # group 3 (all intermediate method names)
(?: # non-capturing group that matches a single method name
[a-z\d]+ # one or more alphanumeric characters
[.] # literal .
)* # end of method name, repeat 0 or more times
) # end of group 3 (intermediate method names);
( # group 4 (final method name and arguments)
[a-z\d]+ # one or or more alphanumeric characters
(?: # non-capturing group for arguments
[(] # literal (
(?1) # recursively apply the pattern inside group 1
(?: # non-capturing group for multiple arguments
[,] # literal ,
(?1) # recursively apply the pattern inside group 1 on parameters
)* # end of multiple arguments group; repeat 0 or more times
[)] # literal )
)? # end of argument-group; make optional
) # end of group 4 (method name and arguments)
) # end of group 1 (recursion group)
[}] # literal }
$ # end of the string
/ix';
$sourcestring='${classA1.methodA0.methodA1.methodB1(classB.methodC(classB.methodD))}';
Array
[1] => Array
(
[0] => classA1
)
[2] => Array
(
[0] => methodA0
)
[3] => Array
(
[0] => methodA1.methodB1(classB.methodC(classB.methodD))
)
)
[2] => Array
(
[0] => methodA0.methodA1
)
[3] => Array
(
[0] => methodB1(classB.methodC(classB.methodD))
)
)
[2] => Array
(
[0] => methodA0
)
[3] => Array
(
[0] => methodA1
)
[4] => Array
(
[0] => methodB1(classB.methodC(classB.methodD))
)
)
最佳答案
这是困难的一个。递归模式通常超出了正则表达式所能提供的范围,即使有可能,也会导致很难理解和维护的表达式变得非常困难。
您正在使用PHP,因此使用的是PCRE,它实际上支持递归正则表达式构造(?n)
。由于您的递归模式非常有规律,因此可以使用正则表达式找到一些实用的解决方案。
我要立即提一个警告:由于您允许每个级别调用任意数量的“中间”方法(在代码段fdsfs
和fsdf
中),因此您无法在单独的捕获中获得所有这些方法。使用PCRE根本不可能。每次匹配将始终产生相同数量的捕获,这取决于您的模式所包含的开括号数量。如果重复使用捕获组(例如,使用诸如([a-z]+\.)+
之类的东西),则每次使用该捕获组时,先前的捕获都会被覆盖,并且您只会得到最后一个实例。因此,我建议您一起捕获所有“中间”方法调用,然后简单地将结果 explode
捕获。
同样,您无法(如果想要)一次捕获多个嵌套级别。因此,您想要的捕获(最后一个包含所有嵌套级别)是唯一的选择-然后您可以将模式再次应用于最后一个匹配,以进一步降低级别。
现在,对于实际表达式:
$pattern = '/
^ # beginning of the string
[$][{] # literal ${
( # group 1, used for recursion
( # group 2 (class name)
[a-z\d]+ # one or more alphanumeric characters
) # end of group 2 (class name)
[.] # literal .
( # group 3 (all intermediate method names)
(?: # non-capturing group that matches a single method name
[a-z\d]+ # one or more alphanumeric characters
[.] # literal .
)* # end of method name, repeat 0 or more times
) # end of group 3 (intermediate method names);
( # group 4 (final method name and arguments)
[a-z\d]+ # one or or more alphanumeric characters
(?: # non-capturing group for arguments
[(] # literal (
(?1) # recursively apply the pattern inside group 1
[)] # literal )
)? # end of argument-group; make optional
) # end of group 4 (method name and arguments)
) # end of group 1 (recursion group)
[}] # literal }
$ # end of the string
/ix';
x
修饰符,该修饰符允许您引入空格和注释,以根据需要设置表达式的格式。没有它们,模式将如下所示:
'/^[$][{](([a-z\d]+)[.]((?:[a-z\d]+[.])*)([a-z\d]+(?:[(](?1)[)])?))[}]$/ix'
i
修饰符略微简化了模式。它只是消除了一些困惑,因为您可以省略字母的大写变体。
[$]
和
[.]
的单字符类来转义字符。这只是一个品味问题,您可以自由使用反斜杠变体。我个人更喜欢字符类的可读性(而且我知道这里的其他人也不同意),所以我也想向您介绍这个选项。
${...}
之外没有无效的语法。
(?n)
与反向引用
\n
相似,因为它引用捕获组
n
(通过从左到右打开括号来计数)。区别在于,反向引用尝试再次匹配组
n
匹配的内容,而
(?n)
再次应用该模式。也就是说
(.)\1
连续两次匹配任何字符,而
(.)(?1)
匹配任何字符,然后再次应用模式,因此匹配了另一个任意字符。如果您在第
(?n)
组中使用这些
n
构造之一,则会获得递归。
(?0)
或
(?R)
指的是整个模式。那就是所有的魔力。
'${abc.def.ghi.jkl(mno.pqr(stu.vwx))}'
0 ${abc.def.ghi.jkl(mno.pqr(stu.vwx))}
1 abc.def.ghi.jkl(mno.pqr(stu.vwx))
2 abc
3 def.ghi.
4 jkl(mno.pqr(stu.vwx))
0
是整个匹配项(在这种情况下,仅是输入字符串)。 PHP将始终首先报告此问题,因此您无法摆脱它。
1
是第一个捕获该递归部分的捕获组。您不需要在输出中使用它,但是不幸的是
(?n)
不能引用非捕获组,因此也需要它。
2
是所需的类名称。
3
是中间方法名称的列表,加上尾随句点。使用
explode
可以很容易地从中提取所有方法名称。
4
是最终的方法名称,带有可选的(递归)参数列表。现在,您可以执行此操作,并在必要时再次应用该模式。请注意,对于完全递归的方法,您可能需要略微修改模式。那就是:在单独的第一步中剥离
${
和
}
,以便整个模式具有与最终捕获完全相同的(递归)模式,并且您可以使用
(?0)
而不是
(?1)
。然后匹配,删除方法名称和括号,然后重复,直到最后一次捕获中不再有括号为止。
if(!preg_match('/^[$][{](.*)[}]$/', $expression, $matches))
echo 'Invalid syntax.';
else
traverseExpression($matches[1]);
function traverseExpression($expression, $level = 0) {
$pattern = '/^(([a-z\d]+)[.]((?:[a-z\d]+[.])*)([a-z\d]+(?:[(](?1)[)])?))$/i';
if(preg_match($pattern, $expression, $matches)) {
$indent = str_repeat(" ", 4*$level);
echo $indent, "Class name: ", $matches[2], "<br />";
foreach(explode(".", $matches[3], -1) as $method)
echo $indent, "Method name: ", $method, "<br />";
$parts = preg_split('/[()]/', $matches[4]);
echo $indent, "Method name: ", $parts[0], "<br />";
if(count($parts) > 1) {
echo $indent, "With arguments:<br />";
traverseExpression($parts[1], $level+1);
}
}
else
{
echo 'Invalid syntax.';
}
}
关于PHP Regex preg_match提取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16987673/
我正在尝试编写一个函数,该函数接受输入字符串、正则表达式(由 std.regex.regex 从原始字符串生成)和错误消息字符串,并尝试匹配来自使用正则表达式输入字符串,如果没有匹配则显示错误消息。到
-edit- 注意 ?末.{2,}? 我发现你可以写 .{2,}? 是不是和下面一模一样? .{2} 最佳答案 号{2,}表示两次或更多次同时 {2}意思是正好两次。量词默认是贪婪的,所以给定字符串
我有以下文字: This is a test ::a. MODE 3 within 7 hours, ::b. MODE 4 within 13 hours, and ::c. MODE 5 with
我用 Regex.fromLiteral(".*") 创建了一个非常简单的匹配所有正则表达式. 根据documentation :“返回指定文字字符串的文字正则表达式。” 但是我真的不明白“对于指定的
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
该Web项目将静态内容放入一些/content/img文件夹中。 网址规则是:/img/{some md5} 但在文件夹中的位置:/content/img/{前两位数字}/ 例子 url:
我有以下数据: SOMEDATA .test 01/45/12 2.50 THIS IS DATA 我想从中提取数字 2.50。我已设法使用以下 RegEx 做到这一点: (?<=\d{2}\/\d{
我需要证明或反驳下面的正则表达式 (RS + R )* R = R (SR + R)* // or, for programmers: /(RS|R)*R/ == /R(SR|R)*/ 我有一种强烈的
对于具有自由文本的字符串: "The shares of the stock at the XKI Market fell by €89.99 today, which saw a drop of a
例如,我有 RegEx DSX-?2 的 var 我需要将此变量添加到 RegEx 并获取此 .match(/DSX-?2/gi) 最佳答案 您可以创建一个 RegExp对象使用 new RegExp
我无法区分大小写的搜索无法在SQLITE中用于REGEX。支持语法吗? SELECT * FROM table WHERE name REGEXP 'smith[s]*\i' 我希望得到以下答案(假设
Visual Studio / XPath / RegEx: 给定表达式: (?(Car|Car Blue)) +(?.+) +---> +(?.+) 给定搜索字符串: Car Blue Flying
我有一个看起来像这样的正则表达式 /^(?:\w+\s)*(\w+)$*/ 什么是?: ? 最佳答案 它表示子模式是非捕获子模式。这意味着在 (?:\w+\s) 中匹配的任何内容,即使它被 () 括起
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我在 Excel 工作表(也以 csv 格式)中获得了姓名列表,并根据姓名来源进行了分组。 这就是我创建的组的样子。 现在我想添加一个新列,名称后面包含组名称。 这就是我想要获得的。 我如何得到这个?
我试图将一个字符串拆分为一个字符串列表,单词是分开的,但是周围的字符,例如.. "?()“”!"也分开。 要分隔的字符串是"testing “testing” “one two three” (hi
我有一个来自视频转换文件的完整日志,它看起来像这样: -------------------------------------------------------------------------
在定界符为“-”的模式 X-Y-Z 中,我想检查 Y 是否具有大小 8 而没有重复。 Y 可以是像 Y = (A-B-C) 这样的子集,但如果没有,则 Y 的值为 1 1 - num-12345678
Java确实有这个功能,谢谢你的回答,对我来说失去对API的关注太可惜了... 例如: String strOriginal = "A:B&C@D"; 我认为java中应该有一个非常好的方法来改变它,
我只需要接受符合这些规则的输入... 0.25-24 0.25 的增量(.00、.25、.50、.75) 第一个数字不是必须的。 希望尾随零是可选的。 一些有效条目的示例: 0.25 .50 .5 1
我是一名优秀的程序员,十分优秀!