是否可以使用.net Regex类对特定捕获组进行替换。
例如
<customer.*?(display="(?:yes|no)")?.*?>
我想匹配Customer xml元素,但在display属性捕获组中替换。我认为这将是第1组,但我总能说出这一点。
答案 0 :(得分:2)
我认为您需要捕获display属性之前和之后的内容。
(<customer.*?)(display="(?:yes|no)")(.*?>)
然后您可以在替换lambda中使用它
Regex.Replace(inputString, @"(<customer.*?)(display=""(?:yes|no)"")(.*?>)", m => String.Format("{0}{1}{2}", m.Groups[1], /* replacement string based on m.Groups[2] */, m.Groups[3]));
答案 1 :(得分:0)
根据安德鲁斯的回答,我通过创建一个处理替换的方法来扩展这一点。在我的情况下,我想替换整个组,所以我创建了一个帮助类来执行此操作。此外,它不需要您创建一个前后捕获组来实现此目的。
/// <summary>
/// A Regular Expression match and replace class
/// </summary>
public class RegexReplacer
{
private readonly int _captureGroupToReplace;
/// <summary>
/// Initialises the RegEx replacer with matching criteria.
/// </summary>
/// <param name="name">A name that identifies this replacement pattern</param>
/// <param name="matchCriteria">A regular Expression used to locate the values to replace</param>
/// <param name="replacementValue">The value that will replace the matched pattern</param>
/// <param name="captureGroupToReplace">The Capture group that should be replaced. The default is the entire match</param>
public RegexReplacer(string name, Regex matchCriteria, string replacementValue, int captureGroupToReplace = 0)
{
_captureGroupToReplace = captureGroupToReplace;
Name = name;
ReplacementValue = replacementValue;
MatchCriteria = matchCriteria;
}
public string Name { get; set; }
public Regex MatchCriteria { get; set; }
public string ReplacementValue { get; set; }
/// <summary>
/// Finds and replaces all instances of a string within the supplied string or replaces a group if the group id is supplied in the constructor
/// </summary>
public string ReplaceInString(string stringToSearch)
{
if (_captureGroupToReplace != 0)
return MatchCriteria.Replace(stringToSearch, new MatchEvaluator(ReplaceGroup));
return MatchCriteria.Replace(stringToSearch, ReplacementValue);
}
private string ReplaceGroup(Match match)
{
try
{
var matchedString = match.Value;
//Match index is based on the original string not the matched string
int groupIndex = match.Groups[_captureGroupToReplace].Index - match.Index;
int groupLength = match.Groups[_captureGroupToReplace].Length;
var preGroupString = matchedString.Substring(0, groupIndex);
var postGroupString = matchedString.Substring(groupIndex + groupLength, matchedString.Length - (groupIndex + groupLength));
var replacedString = String.Format("{0}{1}{2}", preGroupString, ReplacementValue, postGroupString);
return replacedString;
}
catch (Exception)
{
return match.Value;
}
}
}
我还必须修改我的原始模式,这样它会在xml的末尾给我一个空组来插入一个属性,如果它不存在则用法看起来像
var replacer = new RegexReplacer("DisplayCustomerAttribute",
new Regex(@"(?:<customer\s.*?((\sdisplay=""(?:yes|no)"").*?|())>)"),
@" display=""yes""", 1)
xmlString = replacer.ReplaceInString(xmlString);
作为旁注,原因是因为.net xml序列化在值与默认值相同时不包含属性。当你控制消费者时,这是可以的,但在我们的情况下,我们不是这样,我们需要明确。