Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net正则表达式用捕获组替换模式的重复出现_C#_.net_Regex_Vb.net - Fatal编程技术网

C# .Net正则表达式用捕获组替换模式的重复出现

C# .Net正则表达式用捕获组替换模式的重复出现,c#,.net,regex,vb.net,C#,.net,Regex,Vb.net,我有一个SQL脚本,如下所示: DECLARE @MyVariable1 = 1 DECLARE @MyVariable1 = 10 DECLARE @MyVariable3 = 15 DECLARE @MyVariable2 = 20 DECLARE @MyVariable1 = 7 DECLARE @MyVariable2 = 4 DECLARE @MyVariable4 = 7 DECLARE @MyVariable2 = 4 当然,真正的脚本在中间有很多其他的东西,但是我想写一个给定上

我有一个SQL脚本,如下所示:

DECLARE @MyVariable1 = 1
DECLARE @MyVariable1 = 10
DECLARE @MyVariable3 = 15
DECLARE @MyVariable2 = 20
DECLARE @MyVariable1 = 7
DECLARE @MyVariable2 = 4
DECLARE @MyVariable4 = 7
DECLARE @MyVariable2 = 4
当然,真正的脚本在中间有很多其他的东西,但是我想写一个给定上面输入的函数,输出这个:

DECLARE @MyVariable1 = 1
@MyVariable1 = 10
DECLARE @MyVariable3 = 15
DECLARE @MyVariable2 = 20
@MyVariable1 = 7
@MyVariable2 = 4
DECLARE @MyVariable4 = 7
@MyVariable2 = 4
基本上删除已声明变量的重复
DECLARE
语句

我目前的解决方案是:

    Private Function RemoveDuplicateDeclarations(commandText As String) As String
        Dim lines = commandText.Split(New String() { vbCrLf }, StringSplitOptions.RemoveEmptyEntries)
        Dim declarationRegex As New Regex("(\r|\n|\r\n) *DECLARE *(?<initialization>(?<varname>[^ ]*) *.*)" & vbCrLf , RegexOptions.Multiline Or RegexOptions.IgnoreCase)
        Dim declaredVariables As New List(Of String) 
        Dim resultBuilder As New StringBuilder()

        For Each line In lines    
            Dim matches = declarationRegex.Matches(line)
            If matches.Count > 0 Then
                Dim varname = matches(0).Groups("varname").Value
                If declaredVariables.Contains(varname) Then
                    resultBuilder.AppendLine(declarationRegex.Replace(line, "${initialization}"))
                Else 
                    declaredVariables.Add(varname)

                    resultBuilder.AppendLine(line)
                End If
            Else
                resultBuilder.AppendLine(line)
            End If
        Next

        Return resultBuilder.ToString()
    End Function

您可以使用一个简单的正则表达式来搜索行中重复的
@
前缀词,并且只保留循环中的第一个匹配项,直到没有匹配项为止

(?sm)(^DECLARE\s+(@\w+\b).*?)^DECLARE\s+\2
详细信息

  • (?sm)
    -启用多行和单线(DOTALL)模式
  • (^DECLARE\s+(@\w+\b)。*?)
    -组1捕获:
    • ^DECLARE
      -
      在行首声明
    • \s+
      -1个或多个空白符号
    • (@\w+\b)
      -第2组捕获
      @
      和1+个单词字符,直到尾随单词边界
    • *?
      -任何0+字符,尽可能少,直到第一次出现
  • ^DECLARE
    -行开头的
    DECLARE
    子字符串
  • \s+
    -1+空格
  • \2
    -对存储在组2中的值的反向引用
见:


如果您喜欢linq解决方案:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input =
                "DECLARE @MyVariable1 = 1\n" +
                "DECLARE @MyVariable1 = 10\n" +
                "DECLARE @MyVariable3 = 15\n" +
                "DECLARE @MyVariable2 = 20\n" +
                "DECLARE @MyVariable1 = 7\n" +
                "DECLARE @MyVariable2 = 4\n" +
                "DECLARE @MyVariable4 = 7\n" +
                "DECLARE @MyVariable2 = 4\n";

            string pattern = @"@(?'name'[^\s]+)\s+=\s+(?'value'\d+)";

            MatchCollection matches = Regex.Matches(input, pattern);

            string[] lines = matches.Cast<Match>()
                .Select((x, i) => new { name = x.Groups["name"].Value, value = x.Groups["value"].Value, index = i })
                .GroupBy(x => x.name)
                .Select(x => x.Select((y, i) =>  new { 
                    index = y.index,  
                    s = i == 0 
                       ? string.Format("DECLARE @{0} = {1}", x.Key, y.value)  
                       : string.Format("@{0} = {1}", x.Key, y.value) 
                }))
                .SelectMany(x => x)
                .OrderBy(x => x.index)
                .Select(x => x.s)
                .ToArray();

            foreach (string line in lines)
            {
                Console.WriteLine(line);
            }
            Console.ReadLine();

        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Text.RegularExpressions;
使用System.IO;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串输入=
“声明@MyVariable1=1\n”+
“声明@MyVariable1=10\n”+
“声明@MyVariable3=15\n”+
“声明@MyVariable2=20\n”+
“声明@MyVariable1=7\n”+
“声明@MyVariable2=4\n”+
“声明@MyVariable4=7\n”+
“声明@MyVariable2=4\n”;
字符串模式=@“@(?'name'[^\s]+)\s+=\s+(?'value'\d+);
MatchCollection matches=Regex.matches(输入,模式);
字符串[]行=匹配的.Cast()
.Select((x,i)=>new{name=x.Groups[“name”]。Value,Value=x.Groups[“Value”]。Value,index=i})
.GroupBy(x=>x.name)
.Select(x=>x.Select((y,i)=>new{
索引=y.index,
s=i==0
?string.Format(“DECLARE@{0}={1}”,x.Key,y.value)
:string.Format(“@{0}={1}”,x.Key,y.value)
}))
.SelectMany(x=>x)
.OrderBy(x=>x.index)
.选择(x=>x.s)
.ToArray();
foreach(行中的字符串行)
{
控制台写入线(行);
}
Console.ReadLine();
}
}
}

您用C#和VB.NET标记了您的问题,但您的代码在VB.NET中。这是否意味着C#标记可以删除?可以,我标记了C#,因为我不介意是否有人想用C#回答,因为正则表达式在两种环境中的工作原理相同
Dim rx As Regex = New Regex("(?sm)(^DECLARE\s+(@\w+\b).*?)^DECLARE\s+\2")
Dim s As String = "DECLARE @MyVariable1 = 1" & vbCrLf & "DECLARE @MyVariable1 = 10" & vbCrLf & "DECLARE @MyVariable3 = 15" & vbCrLf & "DECLARE @MyVariable2 = 20" & vbCrLf & "DECLARE @MyVariable1 = 7" & vbCrLf & "DECLARE @MyVariable2 = 4" & vbCrLf & "DECLARE @MyVariable4 = 7" & vbCrLf & "DECLARE @MyVariable2 = 4"
Dim res As String
Dim tmp As String = s
res = rx.Replace(s, "$1$2")
While (String.Compare(tmp, res) <> 0)
    tmp = res
    res = rx.Replace(res, "$1$2")
End While
Console.WriteLine(res)
DECLARE @MyVariable1 = 1
@MyVariable1 = 10
DECLARE @MyVariable3 = 15
DECLARE @MyVariable2 = 20
@MyVariable1 = 7
@MyVariable2 = 4
DECLARE @MyVariable4 = 7
@MyVariable2 = 4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input =
                "DECLARE @MyVariable1 = 1\n" +
                "DECLARE @MyVariable1 = 10\n" +
                "DECLARE @MyVariable3 = 15\n" +
                "DECLARE @MyVariable2 = 20\n" +
                "DECLARE @MyVariable1 = 7\n" +
                "DECLARE @MyVariable2 = 4\n" +
                "DECLARE @MyVariable4 = 7\n" +
                "DECLARE @MyVariable2 = 4\n";

            string pattern = @"@(?'name'[^\s]+)\s+=\s+(?'value'\d+)";

            MatchCollection matches = Regex.Matches(input, pattern);

            string[] lines = matches.Cast<Match>()
                .Select((x, i) => new { name = x.Groups["name"].Value, value = x.Groups["value"].Value, index = i })
                .GroupBy(x => x.name)
                .Select(x => x.Select((y, i) =>  new { 
                    index = y.index,  
                    s = i == 0 
                       ? string.Format("DECLARE @{0} = {1}", x.Key, y.value)  
                       : string.Format("@{0} = {1}", x.Key, y.value) 
                }))
                .SelectMany(x => x)
                .OrderBy(x => x.index)
                .Select(x => x.s)
                .ToArray();

            foreach (string line in lines)
            {
                Console.WriteLine(line);
            }
            Console.ReadLine();

        }
    }
}