C# 在记事本++(或通过C)中基于列提取重复行

C# 在记事本++(或通过C)中基于列提取重复行,c#,regex,notepad++,C#,Regex,Notepad++,我有一个文件有一些重复的序列号。我想做的是只展示我的复制品。我的文件如下所示: John Doe 000115 Wilson Chan 000386 Tye Owens 000589 James Peter 000211 Carl Spade 000445 Sally Doe 000213 [path_name_nere.txt] Format=FixedLength Col1=Column1 Text Width 12 Col2=Column2 Text Width

我有一个文件有一些重复的序列号。我想做的是只展示我的复制品。我的文件如下所示:

John Doe    000115   
Wilson Chan 000386
Tye Owens   000589
James Peter 000211
Carl Spade  000445
Sally Doe   000213
[path_name_nere.txt]
Format=FixedLength

Col1=Column1 Text Width 12
Col2=Column2 Text Width 6
序列号从第15位开始,到第17位结束。我期望的输出是:

James Peter 000211    
Sally Doe   000213
莎莉和詹姆斯都是02系列的演员。 我对正则表达式完全陌生,只知道^.{15}[^-].*美元能让我排到第15位。在那之后我陷入困境。
有没有办法在记事本++或VBS中实现这一点?

当您在寻找这样的复制品时,不建议使用正则表达式方法,您可以编写一个小程序,例如,用C语言,将文本拆分为单独的行,从行中创建键值对,键是索引15处长度为2的子字符串,然后分组并获得计数超过一的数据

var txt = @"John Doe    000115   \nWilson Chan 000386\nTye Owens   000589\nJames Peter 000211\nCarl Spade  000445\nSally Doe   000213";
var splits = txt.Split('\n') // Split into lines 
    .Select(m => new KeyValuePair<string,string>(m.Substring(15,2), m)) // Create key value pairs
    .GroupBy(z => z.Key)   // Group by the 2-char substring
    .Where(y => y.Count() > 1);  // Grab only those with the same key
foreach (var x in splits)        // Display the groups
{
    Console.WriteLine("--- {0} ---", x.Key);
    foreach (var y in x)
        Console.WriteLine(y.Value);
}

你有一个平面文件,固定宽度,数据库。由于您提到了.NET语言,因此可以使用OleDb命名空间将文本文件转换为DataTable,然后过滤掉任何唯一的值。以下是执行此操作的步骤:

创建一个新的 连接字符串应遵循的格式 连接字符串的数据源将是文件所在的目录。 使用步骤1中的OLEDB连接创建新连接 命令字符串应为:从[file_name].txt中选择DISTINCT* 使用步骤2中的OleDbCommand创建新的 使用OleDbDataAdapter将固定宽度数据库的内容填充到 我想给你们举个例子,但我对Visual Basic.NET的掌握更为流利。如果您愿意,我可以编辑我的文章,将VB.NET示例包括在内,您可以通过转换器运行它

更新

由于您请求了Visual Basic.NET示例,下面是一个将文件转换为DataTable的函数:

''' <summary>
''' Converts a fixed width database to a .NET DataTable
''' </summary>
''' <param name="path">The location of the text file to convert</param>
''' <param name="headers">Indicates if the fixed width database contains a header row</param>
''' <returns>DataTable</returns>
''' <remarks>Only returns unique rows</remarks>
Private Function ConvertToDataTable(ByVal path As String, ByVal headers As Boolean) As DataTable
    If Not IO.File.Exists(path) Then
        Throw New ArgumentException("The file does not exists.", "path")
    End If

    'Declare an object to return
    Dim dt As DataTable = Nothing

    'Create a connection object
    Dim con As OleDbConnection = Nothing

    'Database junk, always wrap in Try/Catch
    Try
        'Create a new instance the database connection
        con = New OleDbConnection($"Provider=Microsoft.Jet.OleDb.4.0;Data Source={IO.Path.GetDirectoryName(path)};Extended Properties=""Text;HDR={If(headers, "Yes", "No")};FMT=Fixed"";")

        'Create a new instance of a command object
        Using cmd As OleDbCommand = New OleDbCommand($"SELECT * FROM {path}", con)
            'Create a new instance of a dataadapter
            Using adapter As OleDbDataAdapter = New OleDbDataAdapter(cmd)
                'Open the connection
                con.Open()

                'Create a new instance of a DataTable
                dt = New DataTable

                'Fill the data into the DataTable
                adapter.Fill(dt)

                'Close the connection
                con.Close()
            End Using
        End Using
    Catch ex As Exception
        Console.WriteLine(ex.ToString())
    Finally
        'Check if the connection object was initialized
        If con IsNot Nothing Then
            If con.State = ConnectionState.Open Then
                'Close the connection if it was left open(exception thrown)
                con.Close()
            End If

            'Dispose of the connection object
            con.Dispose()
        End If
    End Try

    'Return the converted DataTable
    Return dt
End Function
现在文件已转换为DataTable,您需要过滤DataTable以排除重复项。

使用,这就是我使用的解决方案:

 var text = File.ReadAllText("C:\\johndoe.txt");
 var sw = new StreamWriter("C:\\johndoeduplicates.txt");
 var splits = text.Split('|')
 .Select(m => new KeyValuePair<string, string>(m.Substring(14, 2), m))
 .GroupBy(z => z.Key)
 .Where(y => y.Count() > 1);
  foreach (var x in splits)
  {  
      foreach (var y in x)
       sw.WriteLine(y.Value);
  }
  sw.Close();

它们是连续的吗?试试^.{15}\d{2}.*?:\R.{15}\1.*+它们并不总是连续的,谢谢你提出这一点,我已经编辑了我的问题。好的,这不是正则表达式的工作。您可以将文本拆分为几行,创建键值,键值是索引15处长度为2的子字符串,然后分组并获取计数大于1的键值。在C语言中,这对我来说比较容易。不知道如何在VBScript中实现。我愿意试一试,我对C有一定的了解,你能指导我吗?我会试着想出一个提琴。谢谢你的帮助,我用你的解决方案来对付一个文本文件。@Ichigo:那为什么不接受我的解决方案呢?你用你自己的自定义值发布了相同的解决方案,为什么?对不起,我以为我接受了你的解决方案,我添加了我自己的解决方案,因为我提到我正在从文件中读取。我想添加解决方案,以防其他人需要读取文件而不仅仅是字符串。我重新检查了你的答案。@Ichigo从文件中读取是一件小事。读取文件的方法有很多,file.ReadAllTextpath是您自己真正可以做的,核心是解析代码。@Wiktor Stribiżew Ok,出于好奇,lambda表达式有多强大?我从来没有真正使用过它们。如果我只希望Sally Doe 000213作为输出,因为她在文件中紧随James Peter 000211之后,这可能吗?OleDbDataConnection听起来是一个非常有用的工具,如果可以的话,我希望你添加你的VB.NET示例。我已经编辑了这篇文章以包含VB.NET示例。
 var text = File.ReadAllText("C:\\johndoe.txt");
 var sw = new StreamWriter("C:\\johndoeduplicates.txt");
 var splits = text.Split('|')
 .Select(m => new KeyValuePair<string, string>(m.Substring(14, 2), m))
 .GroupBy(z => z.Key)
 .Where(y => y.Count() > 1);
  foreach (var x in splits)
  {  
      foreach (var y in x)
       sw.WriteLine(y.Value);
  }
  sw.Close();