更改yaml文件中的路径

0 投票
3 回答
1665 浏览
提问于 2025-04-18 00:12

你好,Python和正则表达式的专家们!

我有一个文件夹,里面有很多yaml文件,我需要在这些文件中多处修改一个路径字符串。

一个yaml文件可能长这样:

修改前

- !import ../../../app/app.yml
- !import ../../fw/fw/app.yml
- !import ../../id/id/app.yml

includes:    [ ../, ../../../app/include/, ../../fw/include, ]

includes:
    - ../
    - ../../../app/include/
    - ../../fw/include

需要改成:

想要的结果

- !import ../../../Sys/app/app.yml
- !import ../../Sys/fw/fw/app.yml
- !import ../../id/id/app.yml

includes:    [ ../, ../../../Sys/app/include/, ../../Sys/fw/include, ]

includes:
    - ../
    - ../../../Sys/app/include/
    - ../../Sys/fw/include

... 所以每个路径前面都要加上/Sys,因为文件的位置已经改变了。需要注意的是,有些路径是不能被修改的:'- !import ../../id/id/app.yml' 这个路径就不能改(可能还有其他路径也不能改)。

在上面的例子中,有两个包含标签,因为在需要修改的文件中,这些标签的写法是不同的。

所以我需要一个正则表达式,能够适用于所有这些组合。我尝试了很多次,但在处理这两个包含标签时遇到了困难。

注意:我更倾向于使用简单的文本文件解析,而不是使用pyaml,这样可以避免破坏文件的格式,因为有些文件包含了很多注释。

欢迎任何建议 - 谢谢!

3 个回答

0
import re

pat = re.compile(r"""
((\.\./){2,}) # at least two levels up
(?!id/)       # no replace of id/ paths
(.*?)
""", flags=re.VERBOSE)

print pat.sub(r"\1Sys/\3", yaml)

输出结果:

- !import ../../../Sys/app/app.yml
- !import ../../Sys/fw/fw/app.yml
- !import ../../id/id/app.yml

includes:    [ ../, ../../../Sys/app/include/, ../../Sys/fw/include, ]

includes:
    - ../
    - ../../../Sys/app/include/
    - ../../Sys/fw/include
0

试试这个:

input = re.sub("((?:\.\./)+)(?=[a-zA-Z0-9])", '\\1Sys/', input)

这个代码的意思是:找出连续出现的 ../,如果后面跟着一个字母或数字,就把这个字母或数字放到组 \\1 里。

0

我会用类似这样的东西:

output = re.sub(r"\.\./(?=\w)(?!id)", "../Sys/", input)

regex101 演示

请注意,由于我们对哪些内容不应该被更改的信息有限,所以很难找到一个合适的规则来确保不会替换掉你的一些文件路径。正则表达式是根据模式来工作的,所以如果没有合适的规则,你很可能会遇到一些问题。

撰写回答