正则表达式中的反向引用取反



如果字符串具有以下预测格式:

value = "hello and good morning"

其中"(引号)也可以是'(单引号),并且结束字符('或")将与开始字符相同。我想匹配引号之间的字符串。

bvalues*=s*(["'])([^1]*)1

(两个s允许在=号附近有空格)

第一个"捕获组"(在第一对括号内)-应该匹配开头的引语,应该是'或"然后-我应该允许任何数量的字符不是在第一组中捕获的字符,然后我期望在组中捕获的字符(封闭引号)。

(所需的字符串应该在第二个捕获组中捕获)。
但这行不通。

这样做:

bvalues*=s*(['"])([^"']*)["']

但是我想确保前后引号(双引号或单引号)是相同的


编辑
目标基本上是获得锚的开始标记,锚的class属性中包含了特定的类名,并且我想涵盖类属性中包含(')或(")的罕见情况。

根据这里的所有建议,我使用了以下模式:

<s*bab[^<>]+bclasss*=s*("|'|\"|\')(?:(?!1).)*s*classnames*(?:(?!1).)*1[^>]*>

含义:
找一个打开标签的标志。
允许任何空格。
查找 a.
允许任何非结束标记。
查找"class (any spaces) = (any spaces)"
获取起始引号,下列之一:("或'或"或')。
艾伦·摩尔的回答是:允许开头引号以外的任何字符。
查找classname
允许除开始引号以外的任何字符。
找出与开头相同的结尾引语。
允许任何关闭标记字符。
找到结束标记字符。

不使用反向字符类,而是使用反向forward:

bvalues*=s*(["'])(?:(?!1).)*1

(?:(?!1).)*一次消耗一个字符,之后的 forward已经确认该字符不是捕获组(["''])匹配的字符。一个字符类,无论是否否定,一次只能匹配一个字符。就regex引擎所知,1可以表示任意数量的字符,在这种情况下,没有办法使它相信1只包含"'。因此,您必须使用更通用(但可读性较差)的解决方案。

您可以使用:

bvalues*=s*(['"])(.*?)1

查看

在不知道您需要这些信息的情况下(甚至不知道您使用这个正则表达式的语言或工具),我可以推荐许多路径。

使用这些字符串:

value = "hello and good morning"
value = 'hola y buenos dias'
value = 'how can I say "goodbye" so soon?'
value = 'why didn't you say "hello" to me this morning?'
value = "Goodbye! Please don't forget to write!"
value = 'Goodbye! Please don't forget to write!'

这个表达式:

"((\"|[^"])*)"|'((\'|[^'])*)'

将匹配以下字符串:

"hello and good morning"
'hola y buenos dias'
'how can I say "goodbye" so soon?'
'why didn't you say "hello" to me this morning?'
"Goodbye! Please don't forget to write!"
'Goodbye! Please don't forget to write!'

允许"other"类型的引号或相同类型的引号,当转义为单个时。带引号的字符串的内容属于第1组或第3组。您可以通过获取第一个(或最后一个)字符来确定使用了哪种类型的引号。

如果你需要其中一些东西在特定的匹配组中,请给出更具体的例子(包括不应该工作的东西,但看起来可能很接近)

请询问您是否愿意走这条路,并需要更多的帮助

回答这个问题如何在忽略集合中使用数值引用?

这里的

,因为它被标记为与这个完全相同。

不能在类中指定捕获组。
可以做的是在否定断言中指定字符,如

(["'])((?:(?!1)[Ss])*)(1)

扩大
 ( ["'] )                      # (1)
 (                             # (2 start)
      (?:
           (?! 1 )
           [Ss] 
      )*
 )                             # (2 end)
 ( 1 )                        # (3)

请注意,在原始帖子[^char]通常匹配换行符
也可以,但由于这是JavaScript(旧的JS),点不能被使用。
使用[Ss]代替,它匹配任何字符。

我是在寻找模式匹配的帮助时看到这篇文章的

value="long text with "quoted values" and more"

目前Alan Moore给出的最佳答案非常好,但是没有考虑引号的转义。所以感谢Alan,当允许用:

转义引号时,您可以使用此模式。
bvalues*=s*(["'])(?:(?!(?<!\)1).)*1

奖金信息

也许你在这里寻找的模式与我的目的相同,因此我也将分享我的最终解决方案。我必须匹配几个键值对,格式与html相同——属性通常列在节点中,如:one="first" two="second"

下面的正则表达式将匹配它,并将捕获组命名为keyvalue:

b(?P<key>[^=s]*)s*=s*(["'])(?P<value>(?:(?!(?<!\)2).)*)2

当我们为CMS Effcore编写Markdown解析器时,我们尝试了不同的变体以确保最高的速度。这些变体如下所示:

替换示例:

"markdown *text*"

:

"markdown <em>text</em>"
PHP Code #1 for characters "*"one_answers";_"(贪婪模式):
preg_replace('%'.'([*_])'.'(?<phrase>.+?)'.'\1'.'%sS', '<em>$2<em>', $text);

PHP Code #2 for characters "*"one_answers";_"(反向引用否定):

preg_replace('%'.'([*_])'.'(?<phrase>(?:(?!\1).){1,})'.'\1'.'%sS', '<em>$2<em>', $text);
PHP代码#3 for single character "*"(字符类中的否定):
preg_replace('%'.'([*])'.'(?<phrase>[^*]{1,})'.'[*]'.'%sS', '<em>$2<em>', $text);

Case #1 ("贪心模式")比Case #2 ("反引用中的否定")快。

在1000000次迭代上测试:

  1. 0.0245740413665秒。
  2. 3.3793921470642秒。

最新更新