我正在尝试从特定的标记语言LookML中提取某些数据。如果这是示例代码:
explore: explore_name {}
explore: explore_name1 {
label: "name"
join: view_name {
relationship: many_to_one
type: inner
sql_on: ${activity_type.activity_name}=${activity_type.activity_name} ;;
}
}
explore: explore_name3 {}
然后我会收到一个清单,如下所示:
explore: character_balance {}
label: "name"
join: activity_type {
relationship: many_to_one
type: inner
sql_on: ${activity_type.activity_name}=${activity_type.activity_name} ;;
}```
explore: explore_name4 {}
从本质上讲,我从“探索” 开始比赛,并在找到另一个“ explore” 时结束比赛-然后开始下一场比赛。
这是我之前拥有的东西,它在所有行上都匹配,直到找到;
,这才很好用:'explore:\s[^;]*'
。但是,假设有一个,则以“;”结尾。
我将如何更改它,以消除“探索”和“探索”之间的所有内容?只需替换“;”在我的正则表达式中,用“ explore”代替,只要找到与[e,x,p,l,o,r,e]中的任何内容都匹配的字母,它就会停止-这不是我想要的行为。删除方括号和^最终破坏了所有内容,因此它无法跨多行查询。
我在这里应该做什么?
答案 0 :(得分:1)
天真的方法包括到达下一个“探索”一词。但是,如果由于任何原因,字符串值包含此单词,您将得到错误的结果。如果您尝试在字符串包含嵌套方括号时停止使用大括号,则会出现同样的问题。
这就是为什么我建议对字符串的语法进行更精确的描述,其中考虑了字符串和嵌套的大括号。由于re模块不具有递归功能(用于处理嵌套结构),因此我将使用pypi/regex模块:
import regex
pat = r'''(?xms)
\b explore:
[^\S\r\n]* # optional horizontal whitespaces
[^\n{]* # possible content of the same line
# followed by two possibilities
(?: # the content stops at the end of the line with a ;
; [^\S\r\n]* $
| # or it contains curly brackets and spreads over eventually multiple lines
( # group 1
{
[^{}"]*+ # all that isn't curly brackets nor double quotes
(?:
" [^\\"]*+ (?: \\. [^\\"]* )*+ " # contents between quotes
[^{}"]*
|
(?1) # nested curly brackets, recursion in the group 1
[^{}"]*
)*+
}
)
)'''
results = [x.group(0) for x in regex.finditer(pat, yourstring)]
为更加严格,您可以添加对单引号字符串的支持,还可以使用(*SKIP)(*FAIL)
构造防止模式开头的“ explore:”不在字符串中。
答案 1 :(得分:0)
您可以将非贪婪匹配与前瞻性断言一起使用,以检查是否存在另一个explore:
或字符串的结尾。试试:
答案 2 :(得分:0)
尽管它在Regex中是可行的,但您应该使用能够理解该格式的解析器,因为Regex解决方案非常脆弱。
话虽如此,以下是启用了 DOTALL
模式(其中.
匹配包括换行符的所有字符)的Regex解决方案:
re.findall(r'explore:.*?\}', text, re.DOTALL)
explore:
字面上匹配.*?\}
非贪心地匹配到下一个}
示例:
In [1253]: text = '''explore: character_balance {}
...: explore: tower_ends {
...: label: "Tower Results"
...: join: activity_type {
...: relationship: many_to_one
...: type: inner
...: sql_on: ${activity_type.activity_name}=${wba_fact_activity.activity_name} ;;
...: }
...: }
...: explore: seven11_core_session_start {}'''
In [1254]: re.findall(r'explore:.*?\}', text, re.DOTALL)
Out[1254]:
['explore: character_balance {}',
'explore: tower_ends {\n label: "Tower Results"\n join: activity_type {\n relationship: many_to_one\n type: inner\n sql_on: ${activity_type.activity_name}',
'explore: seven11_core_session_start {}']