更新(见问题结尾)
我见过的文本“搜索和替换”实用程序似乎只能逐行搜索......
是否有一个命令行工具可以定位一个行块(在文本文件中),并将其替换为另一个行块。?
例如:测试文件文件是否包含以下exact group
行:
'Twas brillig, and the slithy toves
Did gyre and gimble in the wabe:
All mimsy were the borogoves,
And the mome raths outgrabe.
'Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
The frumious Bandersnatch!'
我想要这个,这样我就可以替换文件中的多行文本并且知道我没有覆盖错误的行。
我永远不会取代“The Jabberwocky”(刘易斯卡罗尔),但它是一个新颖的例子:)
更新:
..(子更新)我以下关于不使用 sed原因的评论仅适用于以下情况;不要将任何工具推得太远超出其设计意图(我经常使用 sed,并认为它非常宝贵。)
我刚刚发现了一个关于sed以及何时不使用它的有趣网页。
因此,由于所有sed答案,我将发布链接.. 它是sourceforge 上 sed 常见问题解答的一部分
另外,我很确定有某种方法diff
可以完成定位文本块的工作(一旦找到,替换就很直接了;使用head
and tail
)......'diff'转储所有必要的数据,但我还没有弄清楚如何过滤它,......(我还在努力)
这个简单的 python 脚本应该完成任务:
像大多数其他解决方案一样,它的缺点是整个文件一次被吞入内存。但是,对于小文本文件,它应该工作得很好。
方法1:暂时将换行符更改为其他内容
以下代码段用管道交换换行符,执行替换,并将分隔符交换回来。如果它看到的线路非常长,该实用程序可能会阻塞。您可以选择任何要交换的字符,只要它不在您的搜索字符串中。
方法 2:更改实用程序的记录分隔符
awk 和 perl 支持设置两个或多个空行作为记录分隔符。使用 awk,通过
-vRS=
(空RS
变量)。使用 Perl,通过-000
(“段落模式”)或设置$,=""
. 这在这里没有帮助,因为您有一个多段搜索字符串。awk 和 perl 还支持将任何字符串设置为记录分隔符。将
RS
或设置$,
为不在搜索字符串中的任何字符串。方法 3:处理整个文件
一些实用程序很容易让您将整个文件读入内存并对其进行处理。
方法四:程序
逐行阅读。从一个空缓冲区开始。如果您看到“'Twas”行并且缓冲区为空,请将其放入缓冲区中。如果您看到“Did gyre”并且缓冲区中有一行,则将当前行附加到缓冲区,依此类推。如果您刚刚添加了“Bandersnatch line”,则输出替换文本。如果当前行没有进入缓冲区,则打印缓冲区内容,打印当前行并清空缓冲区。
psusi展示了一个 sed 实现。在 sed 中,缓冲区的概念是内置的;它被称为保持空间。在 awk 或 perl 中,您只需使用一个变量(可能是两个,一个用于缓冲区内容,一个用于行数)。
我确信必须有一种方法可以用 sed 做到这一点。经过一番谷歌搜索后,我发现了这个:
http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/
基于此,我最终写了:
sed -n '1h;1!H;${;g;s/foo\nbar/jar\nhead/g;p;}' < x
哪个正确地取了 x 的内容:
富吧
并吐出:
罐头
就算你不喜欢灰白色
sed
的perl
,你也可能会喜欢上灰色的awk
。这个答案似乎是您正在寻找的。我在这里复制它。假设您有三个文件并想needle
用replacement
in替换haystack
:这不涉及正则表达式并支持换行符。它似乎适用于相当大的文件。它确实涉及将整个文件放入内存中,因此它不适用于任意大小的文件。如果您希望它更优雅,可以将整个 shebang 包含在 bash 脚本中,或者将其转换为
awk
脚本。更新:loevborg 的 python 脚本无疑是最简单和最好的解决方案(毫无疑问),我对此非常满意,但我想指出我提出的 bash 脚本(在问题的结尾)远没有看起来那么复杂..我删除了我用来测试它的所有调试渣滓..这里再次没有负担(对于访问此页面的任何人)..它基本上是
sed
一个单线,与十六进制转换前后:只是为了把我的帽子扔进戒指,我想出了一个'sed'解决方案,它不会遇到特殊正则表达式字符的任何问题,因为它甚至没有使用一个!..相反,它适用于文件的Hexdumped版本...
我认为它太“头重脚轻”了,但它可以工作,并且显然不受任何大小限制的限制。GNU sed 具有无限的模式缓冲区大小,这就是 Hexdumped 搜索行块结束的地方。所以在这方面没问题...
我仍在寻找
diff
解决方案,因为它在空白方面会更加灵活(我希望;更快)……但在那之前……这是著名的 Sed 先生。:)该脚本完全按原样运行,并且经过合理评论......
它看起来更大;我只有7行基本代码。
对于半现实的测试,它从古腾堡计划 ( Project Gutenberg ) (363.1 KB) 下载“爱丽丝透过镜子”一书......并用自己的行反转版本替换原来的 Jabberwocky 诗......(有趣的是,它并不多不同的向后阅读:)
PS。我刚刚意识到这种方法的一个弱点是如果您的原始使用 \r\n (0xODOA) 作为换行符,并且您的“要匹配的文本”保存为 \n (0x0A).. 那么这个匹配过程在水......('diff'没有这样的问题)......