我有一个在Python中解析一个swagger的api.json文件的URL。
URL看起来像这样,我想用下划线替换短划线,但只在大括号内。
10.147.48.10:8285/pet-store-account/{pet-owner}/version/{pet-type-id}/pet-details-and-name
因此,{pet-owner}
将变为{pet_owner}
,但pet-store-account
将保持不变。
我正在寻找一个正则表达式,允许我执行非贪婪的搜索,然后对每个搜索结果进行搜索替换。
我正在寻找Python re
方法,但如果你能推荐一个Vim one liner,我也将不胜感激。
预期的最终结果是:
10.147.48.10:8285/pet-store-account/{pet_owner}/version/{pet_type_id}/pet-details-and-name
答案 0 :(得分:2)
前提是您希望所有' {...}'要保持一致的块,您可以使用尾随上下文来确定给定的破折号是否在块内,实际上只是要求它跟随' ...}'在哪里'。'不是' {'
in_channel
...
exp = re.compile(r'(?=[^{]*})-')
答案 1 :(得分:2)
在Vim中使用lookahead和lookbehind:
s/\({[^}]*\)\@<=-\([^{]*}\)\@=/_/g
该模式有三个部分:
\({[^}]*\)\@<=
匹配,但不消耗,一个左大括号,后面跟着一个大括号,紧接在下一个部分后面。
-
匹配连字符。
\([^{]*}\)\@=
匹配,但不会消耗除了前括号之外的任何东西,后面跟一个右括号,紧接在前一部分之前。
在Python正则表达式中不能完全遵循相同的技术,因为它们只允许固定宽度的外观。
<强>结果:强>
之前
outside-braces{inside-braces}out-again{in-again}out-once-more{in-once-more}
后
outside-braces{inside_braces}out-again{in_again}out-once-more{in_once_more}
因为它在连字符之前和之后检查正确位置的大括号,所以这个解决方案(与其他仅使用前瞻断言的方案不同)在无法匹配的大括号中表现得非常明显:
之前
b-c{d-e{f-g}h-i
b-c{d-e}f-g}h-i
b-c{d-e}f-g{h-i
b-c}d-e{f-g}h-i
后
b-c{d-e{f_g}h-i
b-c{d_e}f-g}h-i
b-c{d_e}f-g{h-i
b-c}d-e{f_g}h-i
答案 2 :(得分:1)
Vim中的解决方案:
%s/\({.*\)\@<=-\(.*}\)\@=/_/g
匹配模式的说明:
\({.*\)\@<=-\(.*}\)\@=
\({.*\)\@<= Forces the match to have a {.* behind
- Specifies a dash (-) as the match
\(.*}\)\@= Forces the match to have a .*} ahead
答案 3 :(得分:1)
使用两步法:
import re
url = "10.147.48.10:8285/pet-store-account/{pet-owner}/version/{pet-type-id}/pet-details-and-name"
rx = re.compile(r'{[^{}]+}')
def replacer(match):
return match.group(0).replace('-', '_')
url = rx.sub(replacer, url)
print(url)
哪个收益
10.147.48.10:8285/pet-store-account/{pet_owner}/version/{pet_type_id}/pet-details-and-name
这会查找成对的{
和}
,并将每个-
替换为_
。
<小时/>
编辑:对于一线大师:
url = re.sub(r'{[^{}]+}',
lambda x: x.group(0).replace('-', '_'),
url)
答案 4 :(得分:0)
使用python lookahead忽略括号{}
中包含的字符串:
说明强>
(?=...)
:
匹配如果...
匹配下一个,但不消耗任何字符串。这称为先行断言。例如,Isaac (?=Asimov)
只有在跟随'Asimov'时才匹配'Isaac'。
<强>解决方案强>
a = "10.147.48.10:8285/pet-store-account/**{pet-owner}**/version/**{pet-type-id}**/pet-details-and-name"
import re
re.sub(r"(?=[^{]*})-", "_", a)
<强>输出:强>
'10.147.48.10:8285/pet-store-account/**{pet_owner}**/version/**{pet_type_id}**/pet-details-and-name'
答案 5 :(得分:0)
在Vim中另一种方法是使用sub-replace-expression:
:%s/{\zs[^}]*\ze}/\=substitute(submatch(0),'-','_','g')/g
使用\zs
和\ze
我们设置{
和{}之间的匹配}
个字符。使用\={expr}
会将{expr}
评估为每次替换的替代。在整个匹配substitute({text}, {pat}, {replace}, {flag})
上使用VimScripts替换函数submatch(0)
,将-
转换为_
。
如需更多帮助,请参阅:
:h sub-replace-expression
:h /\zs
:h submatch()
:h substitute()