有特定词边界的正则表达式

时间:2022-01-02 15:43:57

Let's say I have a string of type

假设我有一个类型的字符串

(Price+Discounted_Price)*2-Max.Price

(价格+ Discounted_Price)* 2-Max.Price

and a dictionary containing what to replace for each element

以及一个字典,包含每个元素的替换内容

Price: A1 Discounted_Price: A2 Max.Price:A3

价格:A1 Discounted_Price: A2 Max.Price:A3

How can I replace exactly each phrases, without touching the other. Meaning search for Price should not modify Price in Discounted_Price. The result should be (A1+A2)*2-A3 and not (A1+Discounted_A1) - Max.A1 or anything else

我如何能准确地替换每一个短语,而不触及另一个短语。意思是搜索价格不应该在折扣价格中修改价格。结果应该是(A1+A2)*2-A3,而不是(A1+Discounted_A1) - Max。A1或其他

Thank you.

谢谢你!

2 个解决方案

#1


2  

If your variables can consist of alphanumeric/underscore/dot characters, you can match them with [\w.]+ regex pattern, and add boundaries that include .:

如果您的变量可以由字母数字/下划线/点字符组成,您可以使用[\w]匹配它们。+ regex模式,并添加包含的边界。

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class Test
{
    public static void Main()
    {
        var s = "(Price+Discounted_Price)*2-Max.Price";
        var dct = new Dictionary<string, string>();
        dct.Add("Price", "A1");
        dct.Add("Discounted_Price", "A2");
        dct.Add("Max.Price","A3");
        var res = Regex.Replace(s, @"(?<![\w.])[\w.]+(?![\w.])",     // Find all matches with the regex inside s
            x => dct.ContainsKey(x.Value) ?   // Does the dictionary contain the key that equals the matched text?
                  dct[x.Value] :              // Use the value for the key if it is present to replace current match
                  x.Value);                   // Otherwise, insert the match found back into the result
        Console.WriteLine(res);
    }
}

See the IDEONE demo

看到IDEONE演示

The (?<![\w.]) negative lookbehind fails the match if the match is preceded with a word or a dot char, and the (?![\w.]) negative lookahead will fail the match if it is followed with a word or dot char.

如果匹配之前有一个单词或一个点字符,那么(?! !)负的lookahead将失败匹配,如果后面跟着一个单词或点字符,则负的lookahead将失败匹配。

Note that [\w.]+ allows a dot in the leading and trailing positions, thus, you might want to replace it with \w+(?:\.\w+)* and use as @"(?<![\w.])\w+(?:\.\w+)*(?![\w.])".

注意,[\ w。]+允许在前后的位置点,因此,您可能想要换成\ w +(?:\ \ w +)*和使用@”(? < !(\ w。))\ w +(?:\ \ w +)*(? ![\ w。])”。

UPDATE

更新

Since you have already extracted the keywords to replace as a list, you need to use a more sophisticated word boundary excluding dots:

由于您已经提取了要替换为列表的关键字,所以需要使用更复杂的词边界,不包括点:

var listAbove = new List<string> { "Price", "Discounted_Price", "Max.Price" };
var result = s;
foreach (string phrase in listAbove)
{
    result = Regex.Replace(result, @"\b(?<![\w.])" + Regex.Escape(phrase) +  @"\b(?![\w.])", dct[phrase]);
}

See IDEONE demo.

看到IDEONE演示。

#2


0  

For word boundaries, you can use \b Use: \bPrice\b

对于单词边界,你可以使用\b用法:\bPrice\b

But this will replace Price in Max.Price.

但这将取代价格。

Maybe you want to use regular string replace with:

也许你想用正则字符串替换为:

"Price+" --> A1 + "+"

“价格+”——> A1 +“+”

Example:

例子:

string test = "(Price+Discounted_Price)*2-Max.Price";
string a1 = "7";
string a2 = "3";
string a3 = "4";

test = test.Replace("(Price", "(" + a1);
test = test.Replace("Discounted_Price", a2);
test = test.Replace("Max.Price", a3);

Result:

结果:

test is: (7+3)*2-4

测试是:(7 + 3)* 2 - 4

#1


2  

If your variables can consist of alphanumeric/underscore/dot characters, you can match them with [\w.]+ regex pattern, and add boundaries that include .:

如果您的变量可以由字母数字/下划线/点字符组成,您可以使用[\w]匹配它们。+ regex模式,并添加包含的边界。

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class Test
{
    public static void Main()
    {
        var s = "(Price+Discounted_Price)*2-Max.Price";
        var dct = new Dictionary<string, string>();
        dct.Add("Price", "A1");
        dct.Add("Discounted_Price", "A2");
        dct.Add("Max.Price","A3");
        var res = Regex.Replace(s, @"(?<![\w.])[\w.]+(?![\w.])",     // Find all matches with the regex inside s
            x => dct.ContainsKey(x.Value) ?   // Does the dictionary contain the key that equals the matched text?
                  dct[x.Value] :              // Use the value for the key if it is present to replace current match
                  x.Value);                   // Otherwise, insert the match found back into the result
        Console.WriteLine(res);
    }
}

See the IDEONE demo

看到IDEONE演示

The (?<![\w.]) negative lookbehind fails the match if the match is preceded with a word or a dot char, and the (?![\w.]) negative lookahead will fail the match if it is followed with a word or dot char.

如果匹配之前有一个单词或一个点字符,那么(?! !)负的lookahead将失败匹配,如果后面跟着一个单词或点字符,则负的lookahead将失败匹配。

Note that [\w.]+ allows a dot in the leading and trailing positions, thus, you might want to replace it with \w+(?:\.\w+)* and use as @"(?<![\w.])\w+(?:\.\w+)*(?![\w.])".

注意,[\ w。]+允许在前后的位置点,因此,您可能想要换成\ w +(?:\ \ w +)*和使用@”(? < !(\ w。))\ w +(?:\ \ w +)*(? ![\ w。])”。

UPDATE

更新

Since you have already extracted the keywords to replace as a list, you need to use a more sophisticated word boundary excluding dots:

由于您已经提取了要替换为列表的关键字,所以需要使用更复杂的词边界,不包括点:

var listAbove = new List<string> { "Price", "Discounted_Price", "Max.Price" };
var result = s;
foreach (string phrase in listAbove)
{
    result = Regex.Replace(result, @"\b(?<![\w.])" + Regex.Escape(phrase) +  @"\b(?![\w.])", dct[phrase]);
}

See IDEONE demo.

看到IDEONE演示。

#2


0  

For word boundaries, you can use \b Use: \bPrice\b

对于单词边界,你可以使用\b用法:\bPrice\b

But this will replace Price in Max.Price.

但这将取代价格。

Maybe you want to use regular string replace with:

也许你想用正则字符串替换为:

"Price+" --> A1 + "+"

“价格+”——> A1 +“+”

Example:

例子:

string test = "(Price+Discounted_Price)*2-Max.Price";
string a1 = "7";
string a2 = "3";
string a3 = "4";

test = test.Replace("(Price", "(" + a1);
test = test.Replace("Discounted_Price", a2);
test = test.Replace("Max.Price", a3);

Result:

结果:

test is: (7+3)*2-4

测试是:(7 + 3)* 2 - 4