Conditionally Replace Regex Matches in String

Conditional Regular Expression Replace Where String is NOT in the Initial Expression

There seems to indeed be a way to do that with Notepad++ as it supports conditional replacement, which is detailed in the accepted answer of this question: How to use conditionals when replacing in Notepad++ via regex

But please note that it might be easier and quicker to just do multiple Find/Replace for each of your cases...

Regex replace - Conditionally adding characters

As said in several comments, there is no way to do this in a basic text editor's search and replace. It can only be done with callbacks or external code.

I ended up just doing it in two steps: Replace with \1.\2, and then search and replace any dangling periods.

Conditional replacement of a string using regex?

You can use a negative lookahead assertion:

let updated = s.replace(/@example\/(?!is)/g, replacement)

(?!is) is a negative lookahead assertion that will fail the match when is comes after @example/

Perl: regex for conditional replace?

You don't need two regexes. Capture the C[NI] and retrieve the corresponding replacement value from a hash:

#!/usr/bin/perl
use warnings;
use strict;

my $s = 'ab<(CN)cdXYlm<(CI)efgXYop<(CN)zXYklmn<(CI)efgXYuvw<';

my %replace = (CN => 'ONE', CI => 'TWO');

$s =~ s/(\((C[NI])\).*?)XY.*?</$1$replace{$2}</g;

my $exp = 'ab<(CN)cdONE<(CI)efgTWO<(CN)zONE<(CI)efgTWO<';

use Test::More tests => 1;
is $s, $exp;

Conditionally replace regex matches in string

The c++ (0x, 11, tr1) regular expressions do not really work (stackoverflow) in every case (look up the phrase regex on this page for gcc), so it is better to use boost for a while.

You may try if your compiler supports the regular expressions needed:

#include <string>
#include <iostream>
#include <regex>

using namespace std;

int main(int argc, char * argv[]) {
string test = "test replacing \"these characters\"";
regex reg("[^\\w]+");
test = regex_replace(test, reg, "_");
cout << test << endl;
}

The above works in Visual Studio 2012Rc.

Edit 1: To replace by two different strings in one pass (depending on the match), I'd think this won't work here. In Perl, this could easily be done within evaluated replacement expressions (/e switch).

Therefore, you'll need two passes, as you already suspected:

 ...
string test = "test replacing \"these characters\"";
test = regex_replace(test, regex("\\s+"), "_");
test = regex_replace(test, regex("\\W+"), "");
...

Edit 2:

If it would be possible to use a callback function tr() in regex_replace, then you could modify the substitution there, like:

 string output = regex_replace(test, regex("\\s+|\\W+"), tr);

with tr() doing the replacement work:

 string tr(const smatch &m) { return m[0].str()[0] == ' ' ? "_" : ""; }

the problem would have been solved. Unfortunately, there's no such overload in some C++11 regex implementations, but Boost has one. The following would work with boost and use one pass:

...
#include <boost/regex.hpp>
using namespace boost;
...
string tr(const smatch &m) { return m[0].str()[0] == ' ' ? "_" : ""; }
...

string test = "test replacing \"these characters\"";
test = regex_replace(test, regex("\\s+|\\W+"), tr); // <= works in Boost
...

Maybe some day this will work with C++11 or whatever number comes next.

Regards

rbo

How to conditionally match and replace words in a statement using regex in C#

This is indeed not possible and it should not bother you that it is not possible.

Is it possible to build a submarine just from paper? No. Just need to add a few ingredients.

But were it not for the "only pure regex" constraint, this is what I would have done:

var dictionaryReplace = new Dictionary<string, string>
{
{"round","Ball"},
{"square","Box"},
{"liquid","Water"},
{"hot","Fire"},
};

var Text = "round square unknown liquid";

var Pattern = $"({string.Join("|", dictionaryReplace.Keys)})"; //(round|square|liquid|hot)
var Result = new Regex(Pattern).Replace(Text, x => dictionaryReplace[x.Value]);

Console.WriteLine(Result); //Ball Box unknown Water

How to perform this conditional regex replacement task, using lookarounds for bracket & quotation characters?

Here is a solution with negative lookbehind and negative lookahead.

line = r"""list of str and list of :class:`str` or :class:`string <str>` or Union[str, Tuple[int, str]]"""
pattern = r"(?<![\[`<])(str)(?![\]`>])"
re.sub(pattern, r":class:`str`", line)

Output:

list of :class:`str` and list of :class:`str` or :class:`string <str>` or Union[str, Tuple[int, str]]

Check the Regex on Regex101

UPDATE on question in the comments.

Here is my conditional sub approach,
based on the idea of this approach by @Valdi_Bo

line = r"""list of str and list of :class:`str` or :class:`string <str>` or Union[str, Tuple[int, str]]"""
pattern = r"\bstr\b"
def conditional_sub(match):
if not line[match.start()-1] in ['[', '`','<'] and not line[match.end()] in [']', '`', '>']:
return r":class:`str`"
else:
return r"~str"

re.sub(pattern, conditional_sub, line)

Output:

list of :class:`str` and list of :class:`~str` or :class:`string <~str>` or Union[~str, Tuple[int, ~str]]

match.start() and match.end() are just index numbers. With them we can check for the symbols before/after like in the pattern before and decide what to replace.

Regex with conditional replacement

Java isn't my forte, but as people have mentioned regex might not be the right solution to your question. Just in case you are still interested in a regular expression, I think the following covers all your criteria:

^(?:(?=\d{7,9}$)[01]?|\d*(?=\d{7}$)|)(\d+$)

See the online demo



  • ^ - Start string ancor.
  • (?: - Open non-capturing group.
    • (?=\d{7,9}$- A positive lookahead to assert position when there are 7-9 digits up to end string ancor.
    • [01]? - Optionally capture a zero or one.
    • | - Or:
    • \d* - Capture as many digits but untill:
    • (?=\d{7}$) - Positive lookahead for 7 digits untill end string ancor.
    • | - Or: Match nothing.
    • ) - Close non-capturing group.
  • (\d+$) - Capture all remaining digits in 1st capture group until end string ancor.


Related Topics



Leave a reply



Submit