I use PCRE regular expressions for search and replace very often when working with a text editor and I was left quite unhappy after I found out that in powerful Unix command line tools like perl
, awk
or sed
it's fairly complicated to use a bit advanced multiline regex and requires various hard to remember syntax for various situations.
Is there a command line tool for Linux in which search and replace (for all occurences in the whole file) using a more complex multiline regex is as simple as:
magicregextool 's/.* > (.*) joined the channel\.\n(((?!.* 1円 (was kicked from channel\.|was banned from channel\.)\n).*\n)+?.*1円 disconnected)/2円/' file.txt
i.e. the regex to match is the same as I would place in the search for
field in a text editor, the replacement string can handle multiline regex as well and there's no need for any convoluted syntax?
EDIT:
Per request I'm attaching an input which I'd use the example regex above for and explaining what I want it to actually do.
An input like this:
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
should produce this output:
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
The regex matches any line that contains [username] joined the channel
and looks for a line below it that contains [username] disconnected
unless there is a [username] was kicked from channel.
or [username] was banned from channel.
between those 2 lines.
The replacement string then replaces the matched pattern with every line following the line with [username] joined the channel
effectively deleting the line 2016年05月16日 06:20:13 > user joined the channel.
from the input above.
Most likely doesn't make any sense to you but this is just an example regex similar to one I've dealt with recently. Please keep in mind I'm NOT looking for a solution for this particular problem or similar problems with the Unix tools I listed above. I'm looking for a command line tool which can use unmodified "search for" and replacement strings that I use in a text editor (Geany, in particular but that shouldn't really matter) without complicated syntax or requiring some added programming logic to deal with the multiline "search for" and replacement strings.
2 Answers 2
I'm not sure why Perl isn't acceptable here. On the inputs you provided, this line gives the output you asked for:
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
The -e
argument is exactly the first argument to your magicregextool
except that I added the /mg
regex modifier. This may not be "unmodified" but it doesn't seem unreasonable either. If you don't want to type in the whole line, how about this script as magicregextool
:
#!/usr/bin/perl -0777p
BEGIN { $::arg = shift @ARGV; }
eval $arg;
Or even:
#!/bin/sh
perl -0777pe $*
Then you just type:
magicregextool 's/.* > (.*) joined the channel\.\n(((?!.* 1円 (was kicked from channel\.|was banned from channel\.)\n).*\n)+?.*1円 disconnected)/2円/mg' irc.txt
Which is the same as your sample (again other than adding the /mg
modifier).
An additional benefit to this is that if you are running multiple related search/replace operations on each file, you can put them together in the same script:
#!/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;
you could try this one : https://github.com/sami-fennich/TextTool
or this one : https://github.com/sami-fennich/Edit
-
I think some usage examples that would help the OP achieve their goal would be useful here.BrainStone– BrainStone2025年02月19日 09:30:10 +00:00Commented Feb 19 at 9:30
-
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.2025年02月19日 09:30:26 +00:00Commented Feb 19 at 9:30
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
sed
does.sed --in-place 's/expr/replacement/' /path/to/file
sed
doesn't support multiline regex with such simple syntax and as far as I know it doesn't support lookahead or lookbehind at all.sed -e :a -e '$!{N;b a}' -e other_commands...
. This way you can use multiline regexssed
(super sed) supports perl regexperl
itself cannot do this without some added programming logic dealing with the multiline regex which makes the syntax more complicated.