web-dev-qa-db-ja.com

簡単な複数行の正規表現検索と置換のためのコマンドラインツール

私は検索にPCRE正規表現を使用し、テキストエディターで作業するときに頻繁に置き換えますが、Perlawksedなどの強力なUnixコマンドラインツールでは、少し高度な複数行の正規表現を使用するのはかなり複雑であることがわかった後、非常に不満になりました。さまざまな状況で、覚えにくいさまざまな構文が必要です。

より複雑な複数行の正規表現を使用した検索と置換(ファイル全体で発生するすべての場合)が次のように簡単な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.または[username] was banned from channel.があります2行。

次に、置換文字列は、一致したパターンを[username] joined the channelの行に続くすべての行に置き換え、上記の入力から行2016-05-16 06:20:13 > user joined the channel.を効果的に削除します。

ほとんどの場合、意味がありませんがこれは、最近扱った正規表現の例にすぎません。この特定の問題または同様の問題の解決策を探しているわけではないことに注意してください。上記のUnixツールを使用します。テキストエディタで使用する変更されていない「検索」と置換文字列(特にGeanyですが、実際には問題ではありません)を複雑にすることなく使用できるコマンドラインツールを探しています。構文または複数行の「検索」および置換文字列を処理するための追加のプログラミングロジックが必要です。

6
user2044638

ここで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引数は、/mg正規表現修飾子を追加したことを除いて、magicregextoolの最初の引数です。これは「変更されていない」わけではないかもしれませんが、不合理にも思えません。行全体を入力したくない場合は、このスクリプトをmagicregextoolとして入力してください。

#!/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;
4
user9999999