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

use*_*638 6 command-line software-rec regular-expression

我使用PCRE正则表达式搜索和经常更换使用文本编辑器工作时,我被留下颇为不满后,我发现,在强大的Unix命令行工具一样perlawk或者sed它是相当复杂的使用有点先进的多正则表达式,并要求各难以记住各种情况下的语法。

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

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

即要匹配的正则表达式与我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
Run Code Online (Sandbox Code Playgroud)

应该产生这个输出:

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
Run Code Online (Sandbox Code Playgroud)

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

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

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

use*_*999 5

我不知道为什么 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
Run Code Online (Sandbox Code Playgroud)

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

#!/usr/bin/perl -0777p
BEGIN { $::arg = shift @ARGV; }
eval $arg;
Run Code Online (Sandbox Code Playgroud)

甚至:

#!/bin/sh
perl -0777pe $*
Run Code Online (Sandbox Code Playgroud)

然后你只需输入:

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

这与您的示例相同(除了添加修饰符之外/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;
Run Code Online (Sandbox Code Playgroud)