用于轻松进行多行正则表达式搜索和替换的命令行工具

用于轻松进行多行正则表达式搜索和替换的命令行工具

在使用文本编辑器时,我经常使用 PCRE 正则表达式进行搜索和替换,当我发现在强大的 Unix 命令行工具(如 )中使用 PCRE 正则表达式进行搜索和替换时,我感到非常不高兴,或者perl使用awk有点sed高级的多行正则表达式相当复杂,并且需要各种很难记住各种情况的语法。

Linux 是否有一个命令行工具,其中使用更复杂的多行正则表达式进行搜索和替换(对于整个文件中的所有出现)非常简单:

magicregextool 's/.* > (.*) joined the channel\.\n(((?!.* \1 (was kicked from channel\.|was banned from channel\.)\n).*\n)+?.*\1 disconnected)/\2/' file.txt

即要匹配的正则表达式与我在文本编辑器中放置在字段中的相同search for,替换字符串也可以处理多行正则表达式,并且不需要任何复杂的语法?

编辑:

根据请求,我附加了一个输入,我将使用上面的示例正则表达式来解释我希望它实际执行的操作。

像这样的输入:

2016-05-16 06:17:00 > foobar joined the channel.
2016-05-16 06:17:13 <foobar> hi
2016-05-16 06:18:30 > foobar was kicked from channel.
2016-05-16 06:18:30 > foobar disconnected
2016-05-16 06:20:13 > user joined the channel.
2016-05-16 06:20:38 <user> bye
2016-05-16 06:21:57 > user disconnected

应该产生这个输出:

2016-05-16 06:17:00 > foobar joined the channel.
2016-05-16 06:17:13 <foobar> hi
2016-05-16 06:18:30 > foobar was kicked from channel.
2016-05-16 06:18:30 > foobar disconnected
2016-05-16 06:20:38 <user> bye
2016-05-16 06:21:57 > user disconnected

正则表达式匹配任何包含的行[username] joined the channel,并查找其下面包含的行[username] disconnected 除非这两行之间有一个[username] was kicked from channel.or 。[username] was banned from channel.

然后,替换字符串将匹配的模式替换为该行后面的每一行,并有效地从上面的输入中[username] joined the channel删除该行。2016-05-16 06:20:13 > user joined the channel.

很可能对你来说没有任何意义,但是这只是一个示例正则表达式,类似于我最近处理过的正则表达式。请记住,我并不是在为这个特定问题或上面列出的 Unix 工具的类似问题寻找解决方案。我正在寻找一个命令行工具,它可以使用我在文本编辑器(特别是 Geany,但这并不重要)中使用的未修改的“搜索”和替换字符串,而无需复杂的语法或需要一些添加的编程逻辑处理多行“搜索”和替换字符串。

答案1

我不知道为什么 Perl 在这里不被接受。根据您提供的输入,此行给出您要求的输出:

perl -0777p -e 's/.* > (.*) joined the channel\.\n(((?!.* \1 (was kicked from channel\.|was banned from channel\.)\n).*\n)+?.*\1 disconnected)/\2/mg' irc.txt

除了我添加了正则表达式修饰符之外,该-e参数正是您的第一个参数。这也许不是“未经修改”,但似乎也不无道理。如果您不想输入整行,可以将此脚本编写为:magicregextool/mgmagicregextool

#!/usr/bin/perl -0777p
BEGIN { $::arg = shift @ARGV; }
eval $arg;

甚至:

#!/bin/sh
perl -0777pe $*

然后你只需输入:

magicregextool 's/.* > (.*) joined the channel\.\n(((?!.* \1 (was kicked from channel\.|was banned from channel\.)\n).*\n)+?.*\1 disconnected)/\2/mg' irc.txt

这与您的示例相同(除了添加修饰符之外/mg)。

这样做的另一个好处是,如果您对每个文件运行多个相关的搜索/替换操作,您可以将它们放在同一个脚本中:

#!/usr/bin/perl -0777p
s/.* > (.*) joined the channel\.\n(((?!.* \1 (was kicked from channel\.|was banned from channel\.)\n).*\n)+?.*\1 disconnected)/\2/mg;
s/(some other\n)matched text/\1/mg;

相关内容