Regex заменить несколько групп
Я хотел бы использовать регулярные выражения для замены нескольких групп соответствующей заменой.
Таблица замены:
- & → __amp
- # → __hsh
- 1 → 5
- 5 → 6
Например, для следующей строки ввода
a1asda & FJ # ahdk5adfls
соответствующая строка вывода
a5asda__ampfj__hshahdk6adfls
Есть ли способ сделать это?
Ответы
Ответ 1
Учитывая словарь, который определяет ваши замены:
IDictionary<string,string> map = new Dictionary<string,string>()
{
{"&","__amp"},
{"#","__hsh"},
{"1","5"},
{"5","6"},
};
Вы можете использовать это как для создания регулярного выражения, так и для создания замены для каждого соответствия:
var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Пример в реальном времени: http://rextester.com/rundotnet?code=ADDN57626
В этом случае используется Replace
(docs) которая позволяет вам указать лямбда-выражение для замена.
В комментариях указано, что шаблон поиска с синтаксисом регулярного выражения в нем не будет работать должным образом. Это можно преодолеть, используя Regex.Escape
и незначительное изменение кода выше:
var str = "a1asda&fj#ahdk5adfls";
var regex = new Regex(String.Join("|",map.Keys.Select(k => Regex.Escape(k))));
var newStr = regex.Replace(str, m => map[m.Value]);
// newStr = a5asda__ampfj__hshahdk6adfls
Ответ 2
Как насчет использования string.Replace()
?
string foo = "a1asda&fj#ahdk5adfls";
string bar = foo.Replace("&","__amp")
.Replace("#","__hsh")
.Replace("5", "6")
.Replace("1", "5");
Ответ 3
Подобно Jamiec answer, но это позволяет использовать регулярные выражения, которые не соответствуют тексту точно, например. \.
не может использоваться с ответом Jamiec, потому что вы не можете найти совпадение в словаре.
Это решение основано на создании групп, поиске соответствующей группы и поиске значения замены. Это сложнее, но более гибко.
Сначала сделайте карту списком KeyValuePairs
var map = new List<KeyValuePair<string, string>>();
map.Add(new KeyValuePair<string, string>("\.", "dot"));
Затем создайте свое регулярное выражение так:
string pattern = String.Join("|", map.Select(k => "(" + k.Key + ")"));
var regex = new Regex(pattern, RegexOptions.Compiled);
Затем оценщик совпадений становится немного сложнее:
private static string Evaluator(List<KeyValuePair<string, string>> map, Match match)
{
for (int i = 0; i < match.Groups.Count; i++)
{
var group = match.Groups[i];
if (group.Success)
{
return map[i].Value;
}
}
//shouldn't happen
throw new ArgumentException("Match found that doesn't have any successful groups");
}
Затем вызовите регулярное выражение так:
var newString = regex.Replace(text, m => Evaluator(map, m))
Ответ 4
Учитывая словарь, подобный другим ответам, вы можете использовать "совокупность" для сопоставления каждого шаблона в словаре с заменой. Это даст вам гораздо большую гибкость, чем другие ответы, поскольку у вас могут быть разные варианты регулярных выражений для каждого шаблона.
Например, следующий код будет "руналировать" греческий текст (https://en.wikipedia.org/w/index.php?title=Romanization_of_Greek§ion=3#Modern_Greek, Standard/UN):
var map = new Dictionary<string,string>() {
{"α[ύυ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "av"}, {"α[ύυ]", "af"}, {"α[ϊΐ]", "aï"}, {"α[ιί]", "ai"}, {"[άα]", "a"},
{"β", "v"}, {"γ(?=[γξχ])", "n"}, {"γ", "g"}, {"δ", "d"},
{"ε[υύ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "ev"}, {"ε[υύ]", "ef"}, {"ει", "ei"}, {"[εέ]", "e"}, {"ζ", "z"},
{"η[υύ](?=[άαβγδέεζήηίΐϊιλμνόορύΰϋυώω])", "iv"}, {"η[υύ]", "if"}, {"[ηήιί]", "i"}, {"[ϊΐ]", "ï"},
{"θ", "th"}, {"κ", "k"}, {"λ", "l"}, {"\\bμπ|μπ\\b", "b"}, {"μπ", "mb"}, {"μ", "m"}, {"ν", "n"},
{"ο[ιί]", "oi"}, {"ο[υύ]", "ou"}, {"[οόωώ]", "o"}, {"ξ", "x"}, {"π", "p"}, {"ρ", "r"},
{"[σς]", "s"}, {"τ", "t"}, {"[υύϋΰ]", "y"}, {"φ", "f"}, {"χ", "ch"}, {"ψ", "ps"}
};
var input = "Ο Καλύμνιος σφουγγαράς ψυθίρισε πως θα βουτήξει χωρίς να διστάζει.";
map.Aggregate(input, (i, m) => Regex.Replace(i, m.Key, m.Value, RegexOptions.IgnoreCase));
возврат (без изменения переменной "input":
"o kalymnios sfoungaras psythirise pos tha voutixei choris na distazei."
Вы можете, конечно, использовать что-то вроде:
foreach (var m in map) input = Regex.Replace(input, m.Key, m.Value, RegexOptions.IgnoreCase);
который модифицирует переменную "input".
Также вы можете добавить это для повышения производительности:
var remap = new Dictionary<Regex, string>();
foreach (var m in map) remap.Add(new Regex(m.Key, RegexOptions.IgnoreCase | RegexOptions.Compiled), m.Value);
или сделать статический словарь перезаписи, а затем использовать:
remap.Aggregate(input, (i, m) => m.Key.Replace(i, m.Value));