我有两个文件,我们把它们称为foo.py
和fixed_rule_map
。我需要:
foo.py
查找包含模式 的行rule_map =
。如果这样更简单,那么找到模式 就足够了,但是由于包含 的rule_map
行不止一行,因此在这种情况下我只需要匹配第一个匹配项。foo.py
rule_map
foo.py
用 的内容fix_rule_map_in_foo
(包含一行文本)替换 中的行。
例如foo.py
可能看起来像这样:
class example:
"""some useless text.
"""
rule_map = {'greater': lambda x, y: x > y, 'less': lambda x, y: x < y}
def __init__(self,
rule=None,
):
self._init_rule(rule)
def _init_rule(self, rule):
if rule not in self.rule_map and rule is not None:
raise KeyError(f'rule must be greater, less or None, '
f'but got {rule}.')
self.rule = rule
if self.rule is not None:
self.compare_func = self.rule_map[self.rule]
我想将其更正如下:
class example:
"""some useless text.
"""
rule_map = {'greater': lambda x, y: (x if x is not None else -inf) > (y if y is not None else -inf), 'less': lambda x, y: (x if x is not None else -inf) < (y if y is not None else -inf)}
def __init__(self,
rule=None,
):
self._init_rule(rule)
def _init_rule(self, rule):
if rule not in self.rule_map and rule is not None:
raise KeyError(f'rule must be greater, less or None, '
f'but got {rule}.')
self.rule = rule
if self.rule is not None:
self.compare_func = self.rule_map[self.rule]
因此fixed_rule_map
将是包含
rule_map = {'greater': lambda x, y: (x if x is not None else -inf) > (y if y is not None else -inf), 'less': lambda x, y: (x if x is not None else -inf) < (y if y is not None else -inf)}
笔记因为foo.py
是 Python 文件,所以替换必须保留缩进。
执行替换的命令必须放在 Dockerfile 中,因为必须在构建 Docker 映像时执行替换。Docker 使用/bin/sh
作为 RUN 命令的解释器,而不是/bin/bash
,如果您的解决方案使用,这可能会出现问题bash
。但是,我认为我可以使用 shell 脚本来解决这个问题fix_rule_map_in_foo.sh
:
#! /bin/bash
FOO_PATH = /path/to/foo
<your_solution>
并在 Dockerfile 中添加此行:
RUN fix_rule_map_in_foo.sh
答案1
您可以使用 sed 编辑器的r
命令读取文件的内容并插入,删除后面的原始匹配行:
sed -e '/rule_map = /{r fix_rule_map_in_foo' -e 'd;}' foo.py
默认情况下,新内容将写入标准输出,但 GNU sed 支持就地编辑标志(--in-place
或-i
)。
由于这不涉及任何 shell 构造,因此我思考你可以直接运行它(虽然我不使用docker,所以不确定):
RUN sed -i.bak -e '/rule_map = /{r fix_rule_map_in_foo' -e 'd;}' foo.py
然而,如果您愿意的话,您也可以将其放入 POSIX shell 脚本中。
或者,使用非流编辑器ed
(此做使用 shell 构造,因此必须在脚本中):
#!/bin/sh
printf '%s\n' '/rule_map = /r fix_rule_map_in_foo' '-1d' 'wq' | ed -s foo.py
答案2
您可以使用命令替换将文件中包含的单行设置fix_rule_map_in_foo
为名为 eg 的变量,fix
如下所示:
fix="$(cat fix_rule_map_in_foo)"
如果愿意,您也可以将变量设置为固定字符串(而不是从文件中读取该字符串)像这样:
fix="The substitution string here"
然后将该变量传递给,awk
以便您可以匹配该行并像这样替换它:
awk -v fix="$(cat fix_rule_map_in_foo)" '/rule_map = / {$0 = fix}1' foo.py
这将搜索rule_map =
并替换包含与变量值匹配的行fix
,并打印所有行(修改后)到终端...您可以根据需要将输出重定向到文件,例如>
。
如果您希望编辑文件foo.py
,请像这样使用 GNU awk:
gawk -i inplace -v fix="$(cat fix_rule_map_in_foo)" '/rule_map = / {$0 = fix}1' foo.py