2017-06-01 127 views
2

我想替換我的字符串中只有標籤之間的單詞應該被替換的模式。需要替換的單詞作爲鍵和值對存在於字典中。C#使用字典替換正則表達式匹配模式

目前,這就是我想:

string input = "<a>hello</a> <b>hello world</b> <c>I like apple</c>"; 
string pattern = (@"(?<=>)(.)?[^<>]*(?=</)"); 
Regex match = new Regex(pattern, RegexOptions.IgnoreCase); 
MatchCollection matches = match.Matches(input); 

var dictionary1 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); 
dictionary1.Add("hello", "Hi"); 
dictionary1.Add("world", "people"); 
dictionary1.Add("apple", "fruit"); 

string output = ""; 

output = match.Replace(input, replace => { return dictionary1.ContainsKey(replace.Value) ? dictionary1[replace.Value] : replace.Value; }); 
Console.WriteLine(output); 
Console.ReadLine(); 

利用這一點,它取代,但只有第一個「你好」,而不是第二個。我想在標籤之間替換每個'hello'。

任何幫助將不勝感激。

+0

我覺得你的正則表達式是匹配的標籤之間的值,所以你要更換比賽是'hello','hello world'和'我喜歡蘋果'。你是否想要匹配單個單詞?所以你的輸出應該是' hi嗨人我喜歡水果'? –

+1

在XML上使用正則表達式通常被認爲是一個糟糕的想法。 – Amy

+0

是的,這正是我想要的輸出。我的正則表達式是這裏的問題嗎? –

回答

2

的問題是,比賽是:

  • 你好
  • 的hello world
  • 我喜歡蘋果

所以如hello world不在您的詞典。

基於您的代碼,這可能是一個解決方案:

using System; 
using System.Text.RegularExpressions; 
using System.Collections.Generic; 

public class Program 
{ 
    public static void Main() 
    { 
     var dictionary1 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); 
     dictionary1.Add("hello", "Hi"); 
     dictionary1.Add("world", "people"); 
     dictionary1.Add("apple", "fruit"); 


     string input = "<a>hello</a> <b>hello world</b> <c>I like apple</c>"; 
     string pattern = ("(?<=>)(.)?[^<>]list|" + GetKeyList(dictionary1) + "(?=</)"); 
     Regex match = new Regex(pattern, RegexOptions.IgnoreCase); 
     MatchCollection matches = match.Matches(input); 

     string output = ""; 

     output = match.Replace(input, replace => { 
      Console.WriteLine(" - " + replace.Value); 

      return dictionary1.ContainsKey(replace.Value) ? dictionary1[replace.Value] : replace.Value; 
     }); 
     Console.WriteLine(output); 
    } 

    private static string GetKeyList(Dictionary<string, string> list) 
    { 
     return string.Join("|", new List<string>(list.Keys).ToArray()); 
    } 
} 

小提琴:https://dotnetfiddle.net/zNkEDv

如果有人想挖成這一個告訴我,爲什麼我需要一個「清單|」在列表中(因爲第一項被忽略),我會感激。

+1

這裏是我打印出來的小提琴:https://dotnetfiddle.net/kTP1i3 –

+0

這當然告訴OP什麼問題是...你打算提供一個解決方案? –

+0

請問@MikeMcCaughan – hardkoded

1

這是另一種方法 - 我將字符串解析爲XML,然後選擇包含字典中的鍵的元素,然後替換每個元素的值。
但是,您必須擁有有效的XML文檔 - 您的示例缺少根節點。

var xDocument = XDocument.Parse("<root><a>hello</a> <b>hello world</b> <c>I like apple</c></root>"); 
    var dictionary1 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "hello", "Hi" }, { "world", "people" }, { "apple", "fruit" } }; 

    string pattern = @"\w+"; 
    Regex match = new Regex(pattern, RegexOptions.IgnoreCase); 

    var xElements = xDocument.Root.Descendants() 
         .Where(x => dictionary1.Keys.Any(s => x.Value.Contains(s))); 

    foreach (var xElement in xElements) 
    { 
     var updated = match.Replace(xElement.Value, 
          replace => { 
           return dictionary1.ContainsKey(replace.Value) 
            ? dictionary1[replace.Value] : replace.Value; }); 
     xElement.Value = updated; 
    } 
    string output = xDocument.ToString(SaveOptions.DisableFormatting); 

這種模式的"\w+"匹配單詞,而不是空格。
這LINQ選擇其中的元素值包含您的任何字典的鍵的根節點的後代:

var xElements = xDocument.Root.Descendants().Where(x => dictionary1.Keys.Any(s => x.Value.Contains(s))); 

然後我通過XElement枚舉集合迭代返回並應用替代MatchEvaluator只是字符串值,這是更容易!

最終輸出是<root><a>Hi</a><b>Hi people</b><c>I like fruit</c></root>。然後,您可以刪除打開和關閉<root></root>標記,但我不知道您的完整XML如何。

0

這將做你想做的(從您提供什麼爲止):

private static Dictionary<string, string> dict; 
static void Main(string[] args) 
{ 
    dict = 
    new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) 
     { 
     { "hello", "Hi" }, 
     { "world", "people" }, 
     { "apple", "fruit" } 
     }; 

    var input = "<a>hello</a> <b>hello world</b> apple <c>I like apple</c> hello"; 
    var pattern = @"<.>([^<>]+)<\/.>"; 
    var output = Regex.Replace(input, pattern, Replacer); 

    Console.WriteLine(output); 
    Console.ReadLine(); 
} 

static string Replacer(Match match) 
{ 
    var value = match.Value; 
    foreach (var kvp in dict) 
    { 
    if (value.Contains(kvp.Key)) value = value.Replace(kvp.Key, kvp.Value); 
    } 
    return value; 
}