如何用 sed 一次替换两行并考虑缩进?

如何用 sed 一次替换两行并考虑缩进?

我需要帮助将 Python 文件中的以下两行代码替换为sed.我们正在加载一个处理一些数据的Python文件,因此我们需要将下面两行代码替换为另一行而不影响缩进。

我尝试过sed很多命令,所有命令都适用于普通文本行,但它们都不适用于具有空格/制表符 ^[ \s] 或 ^[ \t] 的行

def get_user_creds(user):
    # some lines of code
    user.invoke()
    user.process(user)

预期的 :

def get_user_creds(user):
    # some lines of code
    user.reinvoke()

答案1

re用 插入所有行user.invoke()并删除所有行将非常容易user.process(user),所以我想问题是只有当这些行一起出现时才更改它们。

在 中sed,当您总是需要一起处理两行时,您可以使用该N;P;D模式,总是附加Next 行,对这两行进行填充,然后Print 并D删除第一行以继续下一行。

在你的情况下:

sed '$!N;s/user.invoke().*\n.*user.process(user)/user.reinvoke()/;P;D'

(目前,我无法测试这一点,但我相信它会起作用。)

答案2

使用(以前称为 Perl_6)

~$ raku -e 'put slurp.subst(:global, / \h+ <( "user.invoke()" \n \h+ "user.process(user)" )> /, "user.reinvoke()" );'  file

输入示例:

def get_user_creds(user):
    # some lines of code
    user.invoke()
    user.process(user)

示例输出:

def get_user_creds(user):
    # some lines of code
    user.reinvoke()

Raku 是 Perl 家族的一种编程语言。上面的文件被slurp编入(即一次读入内存),然后subst使用参数(副词)执行itution :global,这意味着文件中的每两行匹配都将被替换。

匹配器/ \h+ <( "user.invoke()" \n \h+ "user.process(user)" )> /查找两个文字字符串(用双引号括起来),并用适当的空格包围(\h对于水平空格,\n对于换行符)。一旦匹配,<(...)>捕获标记将用于描绘要替换的内容。这里,初始\h+的是不在之内捕获标记,因此保留在输出中,与新插入的字符串相邻(即“尊重缩进”)。

一般来说,转义正则表达式是一件痛苦的事情。然而,Raku 通过允许文字字符串(上面的双引号)简化了该过程。如果引号有问题,那么反斜杠就可以了:只需反斜杠所有非 [alnum 或下划线] 即可按字面意思理解这些字符。这保留了非反斜杠非[数字或下划线]字符(与“”点同一类别.)在将来具有特殊含义,即使目前没有赋予特殊含义。

仅供参考,您可以非常具体地了解捕获/替换。在字符串“user”下方。和“invoke()”被捕获,并在替换中插入“re”以生成“reinvoke()”:

~$ raku -e 'put S:g/ \h+ <( ("user.") ("invoke()") \n \h+ "user.process(user)" )> /$0re$1/ given slurp();'  file

#OR

~$ raku -e 'put S:g[ \h+ <( ("user.") ("invoke()") \n \h+ "user.process(user)" )> ] = "$0re$1" given slurp();'  file

https://docs.raku.org/language/regexes
https://raku.org

相关内容