正则表达式C#是否可以使用替换变量?

时间:2017-04-06 15:10:04

标签: c# regex substitution

我在文本中有一堆字符串,看起来像这样:

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)

输出应为:

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

(最后一个看起来像这样,因为h字母后的值是9,它在输出中假设为9

所以,我开始考虑使用正则表达式。

这里是示例https://regex101.com/r/spb3Af/1/

(正如您所看到的,我想出了像(^(h([\d]+)\.+?)(.+?)$)这样的正则表达式,并试图在其上使用替换<h$3>$4</h$3>

它几乎是我所寻找的,但我需要在标题级别的工作中添加一些逻辑。

是否可以添加任何带有变量的工作?

或者我需要找其他方法? (首先提取所有标题,考虑函数变量和标题值替换em,并且只有在使用正则表达式后我写了?)

4 个答案:

答案 0 :(得分:1)

您可以使用下面使用的Regex来解决问题。

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

让我解释一下我在做什么

// 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)
(.*)$    

括号将把它捕捉到变量中,可以用作&#34; $ 1&#34;第一次捕获和&#34; $ 2&#34;第二次捕获

答案 1 :(得分: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)重载和自定义评估函数。

您当然可以将此解决方案简化为具有内联lambda表达式的单个函数:

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);
}

答案 2 :(得分:1)

您可能使用的正则表达式是

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

如果您需要确保匹配不跨越,则可以将\s替换为[^\S\r\n]。请参阅regex demo

在C#中替换时,将Group 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()));
    }
}

请参阅C# online demo

注意我在.Trim()上使用m.Groups[2].Value作为.匹配\r。您可以使用TrimEnd('\r')来删除此字符。

答案 3 :(得分: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#5版

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);
        }
    }
}