正则表达式获取具有特定开始和结束每个组的组块
Regex get group block with specific start and end each group
如果我们有一些像这样的字符串:
----------DBVer=1
/*some sql script*/
----------DBVer=1
----------DBVer=2
/*some sql script*/
----------DBVer=2
----------DBVer=n
/*some sql script*/
----------DBVer=n
我们可以在第一个 DBVer=1 和第二个 DBVer=1 之间提取脚本,依此类推...使用正则表达式吗?
我想我们必须有一些正则表达式的占位符,如果看到 DBVer=digitA 选择字符串直到 DBVer=digitA 再次选择字符串直到 DBVer=digitA 如果看到 DBVer=digitB 选择字符串直到 DBVer=digitB 等等...
我们可以用正则表达式来实现吗?如果可以的话怎么办?
是的,使用反向引用和环视,您可以捕获脚本:
var pattern = @"(?<=(?<m>-{10}DBVer=\d+)\r?\n).*(?=\r?\n\k<m>)";
var scripts = Regex.Matches(input, pattern, RegexOptions.Singleline)
.Cast<Match>()
.Select(m => m.Value);
在这里,我们使用 (?<m>-{10}DBVer=\d+)
捕获 m
(标记)组,并稍后在正则表达式中使用 \k<m>
重用 m
值以匹配结束标记.
为了.*
匹配换行符,需要开启Singleline
模式。反过来,这意味着我们必须具体说明我们的换行符。在 Singleline
模式下,这些可以通过 \r?\n
以非平台特定的方式进行说明。
试试下面的代码。不是 RegEx,但效果很好。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication6
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
Script.ReadScripts(FILENAME);
}
}
public class Script
{
enum State
{
Get_Script,
Read_Script
}
public static List<Script> scripts = new List<Script>();
public int version { get; set; }
public string script { get; set; }
public static void ReadScripts(string filename)
{
string inputLine = "";
string pattern = "DBVer=(?'version'\d+)";
State state = State.Get_Script;
StreamReader reader = new StreamReader(filename);
Script newScript = null;
while ((inputLine = reader.ReadLine()) != null)
{
inputLine = inputLine.Trim();
if (inputLine.Length > 0)
{
switch (state)
{
case State.Get_Script :
if(inputLine.StartsWith("-----"))
{
newScript = new Script();
scripts.Add(newScript);
string version =
Regex.Match(inputLine, pattern).Groups["version"].Value;
newScript.version = int.Parse(version);
newScript.script = "";
state = State.Read_Script;
}
break;
case State.Read_Script :
if (inputLine.StartsWith("-----"))
{
state = State.Get_Script;
}
else
{
if (newScript.script.Length == 0)
{
newScript.script = inputLine;
}
else
{
newScript.script += "\n" + inputLine;
}
}
break;
}
}
}
}
}
}
如果我们有一些像这样的字符串:
----------DBVer=1
/*some sql script*/
----------DBVer=1
----------DBVer=2
/*some sql script*/
----------DBVer=2
----------DBVer=n
/*some sql script*/
----------DBVer=n
我们可以在第一个 DBVer=1 和第二个 DBVer=1 之间提取脚本,依此类推...使用正则表达式吗?
我想我们必须有一些正则表达式的占位符,如果看到 DBVer=digitA 选择字符串直到 DBVer=digitA 再次选择字符串直到 DBVer=digitA 如果看到 DBVer=digitB 选择字符串直到 DBVer=digitB 等等...
我们可以用正则表达式来实现吗?如果可以的话怎么办?
是的,使用反向引用和环视,您可以捕获脚本:
var pattern = @"(?<=(?<m>-{10}DBVer=\d+)\r?\n).*(?=\r?\n\k<m>)";
var scripts = Regex.Matches(input, pattern, RegexOptions.Singleline)
.Cast<Match>()
.Select(m => m.Value);
在这里,我们使用 (?<m>-{10}DBVer=\d+)
捕获 m
(标记)组,并稍后在正则表达式中使用 \k<m>
重用 m
值以匹配结束标记.
为了.*
匹配换行符,需要开启Singleline
模式。反过来,这意味着我们必须具体说明我们的换行符。在 Singleline
模式下,这些可以通过 \r?\n
以非平台特定的方式进行说明。
试试下面的代码。不是 RegEx,但效果很好。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication6
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
Script.ReadScripts(FILENAME);
}
}
public class Script
{
enum State
{
Get_Script,
Read_Script
}
public static List<Script> scripts = new List<Script>();
public int version { get; set; }
public string script { get; set; }
public static void ReadScripts(string filename)
{
string inputLine = "";
string pattern = "DBVer=(?'version'\d+)";
State state = State.Get_Script;
StreamReader reader = new StreamReader(filename);
Script newScript = null;
while ((inputLine = reader.ReadLine()) != null)
{
inputLine = inputLine.Trim();
if (inputLine.Length > 0)
{
switch (state)
{
case State.Get_Script :
if(inputLine.StartsWith("-----"))
{
newScript = new Script();
scripts.Add(newScript);
string version =
Regex.Match(inputLine, pattern).Groups["version"].Value;
newScript.version = int.Parse(version);
newScript.script = "";
state = State.Read_Script;
}
break;
case State.Read_Script :
if (inputLine.StartsWith("-----"))
{
state = State.Get_Script;
}
else
{
if (newScript.script.Length == 0)
{
newScript.script = inputLine;
}
else
{
newScript.script += "\n" + inputLine;
}
}
break;
}
}
}
}
}
}