我在文本中有一堆字符串,看起来像这样:
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,并且只有在使用正则表达式后我写了?)
答案 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()));
}
}
注意我在.Trim()
上使用m.Groups[2].Value
作为.
匹配\r
。您可以使用TrimEnd('\r')
来删除此字符。
答案 3 :(得分:1)
这个帖子中有很多很好的解决方案,但我认为你真的不需要Regex解决方案来解决你的问题。为了好玩和挑战,这里有一个非正则表达式解决方案:
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);
}
}
}