我有许多文件想要通过将一个多行字符串替换为另一个多行字符串来更新。大致如下:
* Some text,
* something else
* another thing
我想将其替换为:
* This is completely
* different text
结果是,在替换后,包含第一个文本块的文件现在将包含第二个字符串(文件的其余部分保持不变)。
部分问题是我必须在文件系统中找到要更新的文件列表。我想我可以使用 grep 来实现这一点(尽管这对于多行字符串来说并不那么容易做到),然后也许可以将其通过 sed 进行管道传输?
是否有捷径可寻? Sed 是一个选项,但它很尴尬,因为我必须添加 \n 等。有没有办法说“从这个文件中获取输入,在这些文件中匹配它,然后将其替换为另一个文件的内容”?如果需要,我可以使用 python,但我想要一些快速而简单的东西,所以如果有可用的实用程序,我宁愿使用它而不是编写自己的脚本(我知道如何做)。
答案1
在一个或多个输入文件中用文件“new”的内容替换“Some...\n...Thing”
perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
-i
直接更改input.txt-p0
slurp 输入文件 file 并最后打印它s/regexp/.../s
在正则表达式中.
是.|\n
s/.../exp/e
替换为eval(exp)
- new -- 包含替换文本的文件(这是完全...不同的文本)
- 如果有用的话可以扩展原文
s/Some text\n...\n...thing\n/...
答案2
sed -e :n -e '$!N;/\n.*\n/!{$!bn
}; s/some text,\n* *something else\n* *another thing/this is completely\
different text/;P;D' <infile
我担心您将很难找到适合您的解决方案,直到您敲定出问题的具体描述 - 但在我看来,这就是 QA 最适合的工作。也许这会给你一个想法 - 它总是一次在模式空间中保留 3 行 - 具有 2 行前瞻 - 同时在输入文件中一次仅向前滑动一行。
它应该能够匹配您的字符串,无论它是否跨越多行(最多三行)。但是没有在替换中镜像该条款的规定 - 它总是跨越书面的两行。
答案3
尽管ripgrep
特别不支持内联替换,我发现它当前的--replace
功能对于这个用例已经很有用:
rg --replace "$(cat new.txt)" --passthru --no-line-number \
--multiline --multiline-dotall 'Some.*?thing\n' multi.txt > output.txt
--replace 'string'
启用替换模式并设置替换字符串。它还可以通过使用$1
等包含捕获的正则表达式组。$(cat new.txt)
将文件的内容new.txt
作为替换字符串传递。--passthru
是必需的,因为ripgrep
通常只显示与正则表达式模式匹配的行。使用此选项,它还会显示文件中不匹配的所有行。--no-line-number / -N
是因为默认情况下ripgrep
在输出中包含行号(当仅显示匹配的行时很有用)。--multiline / -U
启用多行处理,默认情况下禁用。--multiline-dotall
仅当您希望点 ('.') 正则表达式模式匹配换行符 (\n
) 时才需要。> output.txt
由于不支持内联替换,因此需要。使用--passthrough
和no-line-number
选项,标准输出将所需的新文件与替换项相匹配,并且可以照常保存。
但是,此命令对于处理多个文件不太有用,因为它需要针对每个文件单独运行。
答案4
不太强(因为不要检查第二个字符串,但它很容易解决)并且可以不兼容 posix 但非常简单:
sed '/^Some text/{:1;/another thing$/!{N;b 1}
s/.*/this is completely\ndifferent text/g}' input.txt
第一个命令添加行来自一些文字直到遇见另一件事然后第二行将其更改为其他文本。
笔记限制是一些文字应该始终跟随另一件事。