【问题标题】:Detect all template expressions not enclosed by curly braces检测所有没有被花括号括起来的模板表达式
【发布时间】:2013-10-30 10:13:50
【问题描述】:

我有一个这样的模板字符串:

'%album_artist%/%album%{ (%year%)}/{%track_number%. }%track_artist% - %title%'

我想找到所有不是可选的变量,因此没有用大括号括起来:track_artisttitlealbum_artistalbum 但不是 track_numberyear.

目前,我的表达式是'(?<![{])%([A-Za-z_]+)%(?![}])',但它也匹配year

为了使正则表达式不会被变量名周围的附加字符或花括号内的多个变量所混淆,我必须进行哪些更改?

我使用 Python 的re

相关问题:

【问题讨论】:

  • 你使用什么风格/语言?

标签: python regex regex-lookarounds


【解决方案1】:

如果你使用 PHP,你可以使用这个模式:

~{[^}]*+}(*SKIP)(*FAIL)|%\w++%~i

例子:

preg_match_all('~{[^}]*+}(*SKIP)(*FAIL)|%\w++%~i', $string, $matches);
print_r($matches);

如果您使用 Python,您可以使用捕获组执行相同的技巧(即:匹配大括号中的内容,然后搜索您要查找的内容):

import re

mystr = r'%album_artist%/%album%{ (%year%)}/{%track_number%. }%track_artist% - %title%';
print filter(bool, re.findall(r'{[^}]*|(?i)%(\w+)%', mystr))

注意:

您可以尝试这种其他模式,它将在左大括号后的最后一个 % 处停止匹配(不确定它是否比第一个更快):

print filter(bool, re.findall(r'{(?:[^}%]*%)*|(?i)%(\w+)%', mystr))

【讨论】:

  • 这是什么(*SKIP)(*FAIL) 构造?我从未见过,RegexBuddy 4 也不知道。
  • @TimPietzcker:啊哈!这是一个 PCRE 功能。这些动词是为回溯控制而设计的。 SKIP 表示之前的子模式不能成功,FAIL 会强制子模式失败(如(?!))。目标是避免与\K 不同的空结果
  • 遗憾的是 Python re 不太支持 PCRE。
  • @moi:我添加了 Python 版本。
  • 感谢python版本!如果多个变量用大括号括起来,则第二个版本不起作用,例如str = '%album_artist%/%album%{ (%year%)}/{%track_number%. }{%track_artist% - %title%}'
【解决方案2】:

您可以尝试交替,只对不匹配大括号的分支进行分组。它将返回带有您可以过滤掉的空白字符串的结果,例如:

>>> import re
>>> s = r'''%album_artist%/%album%{ (%year%)}/{%track_number%. }%track_artist% - %title%'''
>>> list(filter(lambda e: e.strip(), re.findall(r'\{[^}]*\}|%([^%]*)%', s)))
['album_artist', 'album', 'track_artist', 'title']

【讨论】:

  • 它有效,谢谢!但是,使用 filter(bool,...) 会更短,就像在 Casimirs 回答中一样。
猜你喜欢
  • 2012-01-18
  • 2020-07-03
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多