如何使用 ruby and/or 正则表达式获取匹配括号内的所有文本
How to grab all text inside of matching brackets with ruby and/or Regular Expressions
我正在清理一些代码,需要确保我的 gsub!
仅 运行 一小部分代码。我需要检查的代码部分以 {{Infobox television
开头(\{\{[Ii]nfobox\s[Tt]elevision
是技术性的)并以 匹配的双括号 "}}".
运行 的 gsub!
的一个例子是 text.gsub!(/\|(\s*)channel\s*=\s*(.*)\n/, "|\1network = \2\n")
...
{{Infobox television
| show_name = 60 Minutos
| image =
| director =
| developer =
| channel = [[NBC]]
| presenter = [[Raúl Matas]] (1977–86)<br />[[Raquel Argandoña]] (1979–81)
| language = [[Spanish language|Spanish]]
| first_aired = {{Date|7 April 1975}}
| website = {{url|https://foo.bar.com}}
}}
...
注:
- 使用
sub
而不是 gsub
不是一种选择,因为可能存在需要替换的参数的多个实例。
- 我不能只查找第一组
}}
,因为可能有多个组,如上例所示。
不花很多时间就不能直接给你答案。
但值得注意的是,第一个括号组在一行的开头,最后一个也是。
所以你有
^{{(.*)^}}$/m
m
表示多行匹配。这将匹配大括号之间的所有内容 - () 括号意味着您可以拉出大括号内匹配的内容,例如:
string = <<_EOT
{{Infobox television
| show_name = 60 Minutos
| image =
| director =
| developer =
| channel = [[NBC]]
| presenter = [[Raúl Matas]] (1977–86)<br />[[Raquel Argandoña]] (1979–81)
| language = [[Spanish language|Spanish]]
| first_aired = {{Date|7 April 1975}}
| website = {{url|https://foo.bar.com}}
}}
_EOT
matcher = string.match(^{{(.*)^}}$/m)
matcher[0]
会给你整个表达式
matcher[1]
会给出 () 括号内匹配的内容
这样做的危险在于它会进行 "greedy" 匹配并匹配最大的文本片段,因此您必须将其关闭。如果没有关于您正在尝试做的事情的更多信息,我将无能为力。
NB - 要匹配 () 括号,您必须将它们转义。有关详细信息,请参阅 https://ruby-doc.org/core-2.1.1/Regexp.html。
您可以使用带有一点递归的正则表达式:
/(?=\{\{[Ii]nfobox\s[Tt]elevision)(\{\{(?>[^{}]++|\g<1>)*}})/
或者,如果里面有单个{
或}
,你还需要匹配那些(?<!{){(?!{)|(?<!})}(?!})
:
/(?=\{\{[Ii]nfobox\s[Tt]elevision)(\{\{(?>[^{}]++|(?<!{){(?!{)|(?<!})}(?!})|\g<1>)*}})/
详情:
(?=\{\{[Ii]nfobox\s[Tt]elevision)
- 确保当前位置后跟 {{Infobox television
之类的字符串(具有不同的大小写) 的正向前瞻
(\{\{(?>[^{}]++|\g<1>)*}})
- 符合以下条件的第 1 组:
\{\{
- {{
子串
(?>[^{}]++|\g<1>)*
- 零次或多次出现:
[^{}]++
- {
和 }
以外的 1 个或多个字符
(?<!{){(?!{)
- {
未包含在其他 {
中
(?<!})}(?!})
- }
未包含在其他 }
中
|
- 或
\g<1>
- 整个第 1 组子模式
}}
- }}
子串
我正在清理一些代码,需要确保我的 gsub!
仅 运行 一小部分代码。我需要检查的代码部分以 {{Infobox television
开头(\{\{[Ii]nfobox\s[Tt]elevision
是技术性的)并以 匹配的双括号 "}}".
运行 的 gsub!
的一个例子是 text.gsub!(/\|(\s*)channel\s*=\s*(.*)\n/, "|\1network = \2\n")
...
{{Infobox television
| show_name = 60 Minutos
| image =
| director =
| developer =
| channel = [[NBC]]
| presenter = [[Raúl Matas]] (1977–86)<br />[[Raquel Argandoña]] (1979–81)
| language = [[Spanish language|Spanish]]
| first_aired = {{Date|7 April 1975}}
| website = {{url|https://foo.bar.com}}
}}
...
注:
- 使用
sub
而不是gsub
不是一种选择,因为可能存在需要替换的参数的多个实例。 - 我不能只查找第一组
}}
,因为可能有多个组,如上例所示。
不花很多时间就不能直接给你答案。
但值得注意的是,第一个括号组在一行的开头,最后一个也是。
所以你有
^{{(.*)^}}$/m
m
表示多行匹配。这将匹配大括号之间的所有内容 - () 括号意味着您可以拉出大括号内匹配的内容,例如:
string = <<_EOT
{{Infobox television
| show_name = 60 Minutos
| image =
| director =
| developer =
| channel = [[NBC]]
| presenter = [[Raúl Matas]] (1977–86)<br />[[Raquel Argandoña]] (1979–81)
| language = [[Spanish language|Spanish]]
| first_aired = {{Date|7 April 1975}}
| website = {{url|https://foo.bar.com}}
}}
_EOT
matcher = string.match(^{{(.*)^}}$/m)
matcher[0]
会给你整个表达式
matcher[1]
会给出 () 括号内匹配的内容
这样做的危险在于它会进行 "greedy" 匹配并匹配最大的文本片段,因此您必须将其关闭。如果没有关于您正在尝试做的事情的更多信息,我将无能为力。
NB - 要匹配 () 括号,您必须将它们转义。有关详细信息,请参阅 https://ruby-doc.org/core-2.1.1/Regexp.html。
您可以使用带有一点递归的正则表达式:
/(?=\{\{[Ii]nfobox\s[Tt]elevision)(\{\{(?>[^{}]++|\g<1>)*}})/
或者,如果里面有单个{
或}
,你还需要匹配那些(?<!{){(?!{)|(?<!})}(?!})
:
/(?=\{\{[Ii]nfobox\s[Tt]elevision)(\{\{(?>[^{}]++|(?<!{){(?!{)|(?<!})}(?!})|\g<1>)*}})/
详情:
(?=\{\{[Ii]nfobox\s[Tt]elevision)
- 确保当前位置后跟{{Infobox television
之类的字符串(具有不同的大小写) 的正向前瞻
(\{\{(?>[^{}]++|\g<1>)*}})
- 符合以下条件的第 1 组:\{\{
-{{
子串(?>[^{}]++|\g<1>)*
- 零次或多次出现:[^{}]++
-{
和}
以外的 1 个或多个字符
(?<!{){(?!{)
-{
未包含在其他{
中
(?<!})}(?!})
-}
未包含在其他}
中
|
- 或\g<1>
- 整个第 1 组子模式}}
-}}
子串