2017-04-06 3 views
1

나는 이런 식으로 뭔가처럼 보이는 텍스트 문자열의 무리, 가지고 :Regex C# 대체 변수를 사용할 수 있습니까?

h1. this is the Header 
h3. this one the header too 
h111. and this 

을 그리고 나는이 텍스트가 호출되어 반복 말할 수에 따라 달라집니다 처리 할 가정 기능을 가지고

public void ProcessHeadersInText(string inputText, int atLevel = 1) 

그렇게 출력이

을 호출 된 경우에 아래처럼 보일 것입니다
ProcessHeadersInText(inputText, 2) 

출력은 다음과 같아야합니다

,536 그래서

, 내가 정규식을 사용하는 방법에 대해 생각하기 시작

<h3>this is the Header<h3> 
<h5>this one the header too<h5> 
<h9 and this <h9> 

(값이 h 편지 후 이상 9을하는 경우는, 출력 9로 가정의 때문에 마지막 하나는 다음과 같습니다). (당신이 볼 수 있듯이 나는이 (^(h([\d]+)\.+?)(.+?)$) 같은 정규식 내놓았다과 <h$3>$4</h$3>에 대체를 사용하려고)

여기

그것은 내가 필요 거의 내가 무엇을 찾고 있어요하지만, 예를 https://regex101.com/r/spb3Af/1/

입니다 일부 논리를 제목 수준의 작업에 추가하십시오.

변수가있는 작업을 대체하여 추가 할 수 있습니까?

아니면 다른 방법을 찾아야합니까? (모든 제목을 먼저 추출하고, 함수 변수와 헤더 값을 고려하여 em을 대체하고, 정규 표현식을 사용한 후에 만 ​​사용합니다.)

+0

5 버전. – Joey

+0

MatcEvaluator를 사용할 수 있습니다. https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.matchevaluator(v=vs.110).aspx (아마도 @Joey가 말하는 것) –

+0

아, 저것은 훌륭합니다. 생각! – DanilGholtsman

답변

1

정규식 사용 할 수 있습니다 당신이 일치하지 있는지 확인해야하는 경우

^h(\d+)\.+\s*(.+) 

입니다 회선을 가로 지르지 않으면 \s[^\S\r\n]으로 바꿀 수 있습니다. regex demo을 참조하십시오.

C# 내부를 바꿀 때 그룹 1 값을 int로 구문 분석하고 Regex.Replace 메서드 내부의 일치 평가 기 내에서 값을 증가시킵니다.

using System; 
using System.Linq; 
using System.Text.RegularExpressions; 
using System.IO; 
public class Test 
{ 
    // Demo: https://regex101.com/r/M9iGUO/2 
    public static readonly Regex reg = new Regex(@"^h(\d+)\.+\s*(.+)", RegexOptions.Compiled | RegexOptions.Multiline); 

    public static void Main() 
    { 
     var inputText = "h1. Topic 1\r\nblah blah blah, because of bla bla bla\r\nh2. PartA\r\nblah blah blah\r\nh3. Part a\r\nblah blah blah\r\nh2. Part B\r\nblah blah blah\r\nh1. Topic 2\r\nand its cuz blah blah\r\nFIN"; 
     var res = ProcessHeadersInText(inputText, 2); 
     Console.WriteLine(res); 
    } 
    public static string ProcessHeadersInText(string inputText, int atLevel = 1) 
    { 
     return reg.Replace(inputText, m => 
      string.Format("<h{0}>{1}</h{0}>", (int.Parse(m.Groups[1].Value) > 9 ? 
       9 : int.Parse(m.Groups[1].Value) + atLevel), m.Groups[2].Value.Trim())); 
    } 
} 

m.Groups[2].Value.으로 경기 \r에 내가 .Trim()을 사용하고있는 C# online demo

참고를 참조하십시오 여기에

은 당신을 도울 것입니다 예제 코드입니다. 이 문자를 제거하려면 TrimEnd('\r')을 사용할 수 있습니다.

+1

위와 같은 정답을 주셔서 감사합니다. Wiktor! – DanilGholtsman

1

다음과 같이 Regex를 사용하여 문제를 해결할 수 있습니다.

Regex.Replace(s, @"^(h\d+)\.(.*)$", @"<$1>$2<$1>", RegexOptions.Multiline) 

제가 괄호가 두 번째 캡처

에 대한 첫 번째 캡처 "$ 1"과 "$ 2"로 사용할 수있는 변수로를 캡처합니다

// This will capture the header number which is followed 
// by a '.' but ignore the . in the capture 
(h\d+)\. 

// This will capture the remaining of the string till the end 
// of the line (see the multi-line regex option being used) 
(.*)$  

를하고있는 중이 야 무엇을 설명하게

+0

나는 이것이 OP의 질문에 완전히 대답했다고 생각하지 않는다. h 번호 값은 9보다 크지 않고 설정된 금액만큼 증가시킬 수 있도록 조작해야합니다. –

+0

도움이 되셨습니다. 감사합니다. – DanilGholtsman

1

이 시도 :

private static string ProcessHeadersInText(string inputText, int atLevel = 1) 
{ 
    // Group 1 = value after 'h' 
    // Group 2 = Content of header without leading whitespace 
    string pattern = @"^h(\d+)\.\s*(.*?)\r?$"; 
    return Regex.Replace(inputText, pattern, match => EvaluateHeaderMatch(match, atLevel), RegexOptions.Multiline); 
} 

private static string EvaluateHeaderMatch(Match m, int atLevel) 
{ 
    int hVal = int.Parse(m.Groups[1].Value) + atLevel; 
    if (hVal > 9) { hVal = 9; } 
    return $"<h{hVal}>{m.Groups[2].Value}</h{hVal}>"; 
} 

그럼 그냥

전화

ProcessHeadersInText (input, 2);


이 지정 평가 함수와 Regex.Replace(string, string, MatchEvaluator, RegexOptions) 과부하를 이용한다.

당신은 물론 인라인 람다 식으로 하나의 함수에이 솔루션을 간소화 할 수 있습니다 :

public static string ProcessHeadersInText(string inputText, int atLevel = 1) 
{ 
    string pattern = @"^h(\d+)\.\s*(.*?)\r?$"; 
    return Regex.Replace(inputText, pattern, 
     match => 
     { 
      int hVal = int.Parse(match.Groups[1].Value) + atLevel; 
      if (hVal > 9) { hVal = 9; } 
      return $"<h{hVal}>{match.Groups[2].Value}</h{hVal}>"; 
     }, 
     RegexOptions.Multiline); 
} 
+0

오 와우, interesing, 결코 전에 그런 식으로 사용하지 마십시오 (EvaluateHeaderMatch에서와 같이)! – DanilGholtsman

1

이 스레드에서 좋은 해결책이 많이 있지만 문제에 대한 Regex 솔루션이 정말로 필요하다고 생각하지 않습니다. 여기에 재미와 도전이 아닌 정규식 솔루션의 경우 :

Try it online!

using System; 
using System.Linq; 

public class Program 
{ 
    public static void Main() 
    { 
     string extractTitle(string x) => x.Substring(x.IndexOf(". ") + 2); 
     string extractNumber(string x) => x.Remove(x.IndexOf(". ")).Substring(1); 
     string build(string n, string t) => $"<h{n}>{t}</h{n}>"; 

     var inputs = new [] { 
      "h1. this is the Header", 
      "h3. this one the header too", 
      "h111. and this" }; 

     foreach (var line in inputs.Select(x => build(extractNumber(x), extractTitle(x)))) 
     { 
      Console.WriteLine(line); 
     } 
    } 
} 

나는 C# 7 중첩 된 함수와 C# 6 보간 문자열을 사용합니다. 원한다면, 더 많은 레거시 C#을 사용할 수 있습니다. 코드는 읽기 쉬워야하며 필요한 경우 주석을 추가 할 수 있습니다.


C#을 당신은 방금 대체 문자열 대신 대리자를 사용할 수 있습니다

using System; 
using System.Linq; 

public class Program 
{ 
    static string extractTitle(string x) 
    { 
     return x.Substring(x.IndexOf(". ") + 2); 
    } 

    static string extractNumber(string x) 
    { 
     return x.Remove(x.IndexOf(". ")).Substring(1); 
    } 

    static string build(string n, string t) 
    { 
     return string.Format("<h{0}>{1}</h{0}>", n, t); 
    } 

    public static void Main() 
    { 
     var inputs = new []{ 
      "h1. this is the Header", 
      "h3. this one the header too", 
      "h111. and this" 
     }; 

     foreach (var line in inputs.Select(x => build(extractNumber(x), extractTitle(x)))) 
     { 
      Console.WriteLine(line); 
     } 
    } 
} 
+0

최신 C# 기능은 무엇입니까? 아직도 내 자신을 강제로 캔트하지 마십시오 – DanilGholtsman

+0

@ DanilGholtsman 그것은 대리인 대신 람다처럼 단지 설탕입니다. – aloisdg

+0

그래, 나도 알아, 그냥 알기 힘들어. – DanilGholtsman