尝试替换HTML文档中的字符串并添加额外的字符

时间:2012-07-09 18:17:13

标签: c# html regex replace

我要做的是打开一个文件并搜索“searchText”。我想用一个新的链接替换文件中的所有实例,这实际上只是带有achor链接的文件名,所以不是打开javascript而只是转到页面中的另一个点。

到目前为止,我所拥有的是:

private void writeNotes(){
        StreamReader reader = new StreamReader(openFileDialog1.FileName);
        string content = reader.ReadToEnd();

        reader.Close();

        string fileName = openFileDialog1.SafeFileName;
        string searchText = "<a class=\"x-fn\" href=\"javascript:void(0);\">";
        string replaceText = "<a class=\"x-fn\" href=\"" + fileName + "#fn" + "\">";

        content = Regex.Replace(content, searchText, replaceText);

        StreamWriter writer = new StreamWriter(openFileDialog1.FileName);
        writer.Write(content);
        writer.Close();

然而,在写完和关闭之后......我打开文件并且没有进行任何更改。除此之外,我想要做的是为每个替换实例添加一个在“#fn”之后计数的数字。所以,基本上,每次我用另一个替换javascript链接时,我希望它是:

<a class="x-fn" href="fileName#fn1">

然后当我替换第二个javascript实例时,它会读取

<a class="x-fn" href="fileName#fn2">

依旧......

我想我必须计算javascript出现次数的实例,替换它,并使用for循环遍历所有新链接并在末尾添加#fn(n)?

2 个答案:

答案 0 :(得分:2)

你的问题是你有元字符(在这种情况下,打开和关闭paren in“void(0)”)。而不是表示文字的开放和关闭的parens,而是创建一个正则表达式组,这会导致您的匹配失败。如果你用反斜杠逃避parens,它将按预期工作。

但是,由于您只是匹配字符串文字,因此根本不需要使用正则表达式;使用string.Replace会更快。

关于你问题的第二部分,这有点棘手。我知道没有简单的方法可以做到这一点,所以最好的方法是在输入中查找搜索文本,然后在进行时建立StringBuilder,递增计数变量。在下面的例子中,为了简单起见,单词“the”被“(0)”和“(1)”替换,但你可以很容易地使它适应你的问题。

var content = "the quick brown fox jumped over the lazy dog";
var searchText = "the";
var sb = new StringBuilder();
var idx = -1; // will hold the index of our search text
var uncopiedIdx = 0; // the start index of what hasn't been copied yet
var replacementCount = 0;
while( (idx = content.IndexOf( searchText, idx+1 )) != -1 ) {
    // copy everything leading up to our search text
    sb.Append( content.Substring( uncopiedIdx, idx-uncopiedIdx ) );
    // copy the replacement text, with the replacement count
    var replacement = "(" + replacementCount++ + ")";
    sb.Append( replacement );
    // skip over the search text
    uncopiedIdx = idx + searchText.Length;
}
// copy everything after the last match
sb.Append( content.Substring( uncopiedIdx ) );

答案 1 :(得分:1)

您可以使用MatchEvaluator,它应该一次完成所有操作 像这样的东西 -

C#

string content = 
 @"
     <a class=""x-fn"" href=""javascript:void(0);"">
     <a class='x-fn' href = ""javascript:void(0); "">
     <a href='javascript:void(0);' class=x-fn >
     <a class=""x-fn"" href=javascript:void(0); >
     <a 'hello' href=javascript:void(0); world class=x-fn >
  ";
 string fileName = "FILE";

 Regex jsRx =  new Regex(
  @"
     <a 
         (?=\s) 
         (?= 
             (?: [^>""']|""[^""]*""|'[^']*')*? (?<=\s)
             class \s*=
             (?:
                 (?> \s* (['""])  \s* x-fn  \s* \1 )         # (1) quote
               | (?> (?!\s*['""]) \s* x-fn  (?=\s|>)   )
             )
         )
         (?= 
             ( (?: [^>""']|""[^""]*""|'[^']*')*? ) (?<=\s)       # (2) - before 'href'
             href \s*=
             (?:
                 (?> \s* (['""])  \s* javascript:void\(0\); \s* \3   )   # (3) quote
               | (?> (?!\s*['""]) \s* javascript:void\(0\); (?=\s|>) )
             )
             ( (?> (?:"".*?""|'.*?'|[^>]?)+ ) )                  # (4) - after 'href'
         )
         (?> \s+ (?:"".*?""|'.*?'|[^>]*?)+ 
     >        
         ) (?<! /> )
  ", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);

 int counter = 0;
 string contentNew = jsRx.Replace( content, delegate(Match match)
 {
     return "<a" + match.Groups[2] + "href=\"" + fileName + "#fn" + (counter++) + "\"" + match.Groups[4] + ">";
 });

 Console.WriteLine( contentNew );

输出

<a class="x-fn" href="FILE#fn0">
<a class='x-fn' href="FILE#fn1">
<a href="FILE#fn2" class=x-fn >
<a class="x-fn" href="FILE#fn3" >
<a 'hello' href="FILE#fn4" world class=x-fn >