如何用文件中的单个单词替换多行(就地替换)?

如何用文件中的单个单词替换多行(就地替换)?

我的文件内容filename如下(例如):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

我想用一个单词替换START和之间的行块,例如用。如下所示:ENDSINGLEWORD

My block of line starts from here 
SINGLEWORD
and end to here for example.

我可以使用以下命令找到我的行块:

grep -Pzo "START(.|\n)*END" filename

上述命令的运行结果如下:

START
First line
second line
third line
END

然后我使用此命令将所有行合并为一行:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

然后我会得到这个结果:

START First line second line third line END

使用我的最后一个命令,LAST_RESULTS | sed 's/.*/SINGLEWORD/'我将它们更改为"SINGLEWORD"并得到了这个结果。

SINGLEWORD

现在我想要的是:如何使用此命令(或您的建议命令)并将我的行块替换为“SINGLEWORD”单词?最终结果将类似于此文件:

My block of line starts from here 
SINGLEWORD
and end to here for example.

答案1

这可以很容易地完成perl

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

解释

-0将行分隔符设置为空

-p将给出的脚本应用-e到每一行并打印该行

正则表达式修饰符:

  • /s将字符串视为单行。也就是说,将其更改.为匹配任何字符,甚至是换行符,而换行符通常不会匹配。

为什么?

  • 默认情况下,量化子模式是“贪婪的”,也就是说,它会匹配尽可能多的次数(给定一个特定的起始位置),同时仍允许其余模式匹配。如果您希望它匹配的次数尽可能少,请在量词后加上?

答案2

我想知道如果没有和其他方法perl,这是否可行python。我使用以下方法找到了解决方案sed

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

解释:

  1. :A 创建标签“a”
  2. 将下一行附加到模式空间
  3. $! 如果不是最后一行 分支(转至)标签 'a'
  4. s 代替/START.*END/经过SINGLEWORD/G 全局匹配(尽可能多次)

它被找到了这里

答案3

尽管ripgrep 不支持内联替换,我发现它的当前--replace功能对于这种用例已经很有用:

rg --replace 'SINGLEWORD' --passthru --no-line-number \
--multiline --multiline-dotall 'START.*?END' input.txt > output.txt

解释:

  • --replace 'SINGLEWORD'启用替换模式并设置替换字符串。可以使用$1等包含捕获的正则表达式组。
  • --passthru是必需的,因为ripgrep通常只显示与正则表达式模式匹配的行。使用此选项,它还会显示文件中所有不匹配的行。
  • --no-line-number / -N是因为默认情况下ripgrep在输出中包含行号(当仅显示匹配的行时很有用)。
  • --multiline / -U启用多行处理,因为它默认是禁用的。
  • --multiline-dotall仅当您想让点('.')正则表达式模式匹配换行符(\n)时才需要。
  • > output.txt是必需的,因为不支持内联替换。使用--passthroughno-line-number选项,标准输出会将所需的新文件与替换文件匹配,并且可以照常保存。

但是,此命令对于处理多个文件不太有用,因为它需要针对每个文件单独运行。

相关内容