2012-07-09 4 views
0

내가하려는 것은 파일을 열고 "searchText"를 검색하는 것입니다. 나는 파일의 모든 인스턴스를 새 링크로 바꾸고 싶습니다. 실제로 링크가있는 파일 이름이므로 자바 스크립트를 여는 대신 페이지의 다른 지점으로 이동합니다.HTML 문서에서 문자열 바꾸기 및 추가 문자 추가

지금까지 내가 무엇을 이것이다 :

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"이후에 카운팅하는 숫자를 추가하는 것입니다.

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

그리고 자바 스크립트의 두 번째 인스턴스를 교체 할 때 다음, 그것은

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

등 읽 그래서, 기본적으로, 모든 시간 동안 나는 내가 원하는, 서로 자바 스크립트 링크를 교체 on ...

자바 스크립트가 나타나는 횟수를 계산하고 바꿔서 for 루프를 사용하여 모든 새 링크를 반복하고 #fn (n)을 끝?

+3

당신은 당신이 바로,뿐만 아니라 HTML 편집을위한 HtmlAgilityPack을 사용할 수 있습니다 알아? –

+1

정규식을 사용하는 이유는 무엇입니까? 간단한 문자열 치환은 할 것이다 .. 특히 검색 문자열이 정규 표현식이 아니기 때문에! – banging

+0

디버거를 사용하십시오. 어쩌면 당신의 정규식이 일치하는 것을 찾지 못할 수도 있습니다. 나는 또한 문자열 바꾸기를 사용하는 것이 좋다고 말했다. 그런 식으로 특별한 정규식 기호에 대해 걱정할 필요가 없습니다. –

답변

2

문제는 메타 문자가있는 것입니다 (이 경우에는 "void (0)"의 개폐 문자가 있음). 문자 그대로 열린 괄호와 닫는 괄호를 나타내는 대신 정규 표현식 그룹이 만들어져 일치하지 않게됩니다. 백 슬래시로 괄호를 벗어나면 예상대로 작동합니다.

그러나 문자열 리터럴과 일치하기 때문에 정규 표현식을 전혀 사용할 필요가 없습니다. 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)); 
+0

'Regex.Escape'를 사용하여 문자열이 정규 표현식의 모든 리터럴로 취급되도록 할 수 있습니다. – Servy

+0

좋아요, 저는 Regex를 제거하고 대신에 string.Replace를 사용했습니다. 그러나, 나는 그것을 실행 한 후에도 변경되지 않습니다. 우연히 그것을 잘못 저장하고 있습니까? 당신의 도움을 주셔서 감사합니다! – JMarsh

+0

경로를 포함하지 않는'SafeFileName' 파일을 열었습니다. 경로를 포함하고있는'FileName'으로 파일을 저장하고 있습니다.따라서 파일을 여는 다른 위치에 파일을 저장할 수 있습니다 .... –

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 > 
+0

당신의 아이디어에 감사드립니다! – JMarsh

+0

환영합니다! 그것의 해결책 thats는 완벽한 년을 걸렸다. 더 이상 생각할 필요가 없습니다. – sln