0

私がやろうとしているのは、ファイルを開いて「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 の 2 番目のインスタンスを置き換えると、次のようになります。

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

等々...

JavaScript が表示される回数のインスタンスを数えて置き換え、for ループを使用してすべての新しいリンクを反復処理し、最後に #fn(n) を追加する必要があると思いますか?

4

2 に答える 2

2

問題は、メタ文字 (この場合、「void(0)」の開き括弧と閉じ括弧) があることです。リテラルの開き括弧と閉じ括弧を表す代わりに、正規表現グループを作成しているため、一致が失敗します。バックスラッシュで括弧をエスケープすると、期待どおりに機能します。

ただし、文字列リテラルに一致させるだけなので、正規表現を使用する必要はまったくありません。使用する方が速くなりますstring.Replace

質問の 2 番目の部分については、少しトリッキーです。私が知っている簡単な方法はありません。そのため、最善の方法は、入力で検索テキストを検索しStringBuilder、カウント変数を増やしながら a を作成することです。次の例では、わかりやすくするために「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 ) );
于 2012-07-09T18:30:55.493 に答える
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 >
于 2012-07-09T20:14:13.127 に答える