Tengo un archivo que tiene algunos números de secuencia duplicados. Lo que quiero hacer es mostrar solo mis duplicados. Mi archivo se ve así:

John Doe    000115   
Wilson Chan 000386
Tye Owens   000589
James Peter 000211
Carl Spade  000445
Sally Doe   000213

El número de secuencia comienza en el lugar 15 y termina en el lugar 17. Mi salida deseada es:

James Peter 000211    
Sally Doe   000213

Sally y James ambos de la secuencia de 02. Soy completamente nuevo con regex y solo descubrí que ^(.{15})[^-](.*)$ me lleva al puesto 15. Estoy atrapado después de eso. ¿Hay alguna manera de lograr esto en notepad ++ o a través de VBS?

1
Ichigo 20 oct. 2017 a las 22:39

3 respuestas

La mejor respuesta

Un enfoque regex no es aconsejable cuando busca duplicados como este, puede escribir un pequeño programa, por ejemplo, en C #, para dividir el texto en líneas separadas, crear pares clave-valor fuera de las líneas, siendo las claves el subcadenas de longitud 2 en el Índice 15, luego agrupe y obtenga las que cuenten más de una.

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

Consulte la demostración de C #

Salida:

--- 21 ---
James Peter 000211
Sally Doe   000213
2
Wiktor Stribiżew 20 oct. 2017 a las 20:57

Con ayuda de Wiktor Stribiżew, esta es la solución que utilicé:

 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();
0
Petter Friberg 23 oct. 2017 a las 18:04

Tiene un archivo plano, ancho fijo, base de datos. Como mencionó un lenguaje .NET, puede usar el espacio de nombres OleDb para convertir el archivo de texto en una DataTable, luego filtraría los valores únicos. Estos son los pasos para hacer eso:

  1. Crear una nueva OleDbDataConnection
    1. La cadena de conexión debe seguir el formato para Columnas de longitud fija
    2. La fuente de datos de la cadena de conexión sería el directorio en el que reside el archivo.
  2. Crear una nueva OleDbCommandutilizando OleDbConnection del paso 1
    1. La cadena de comando debe ser: SELECT DISTINCT * FROM [file_name].txt
  3. Cree un nuevo OleDbDataAdapter usando el OleDbCommand del paso 2
  4. Utilice el Método de relleno para llenar el método de relleno de OleDbDataAdapter. el contenido de la base de datos de ancho fijo en un DataTable

Le daría un ejemplo, pero soy más fluido en Visual Basic .NET. Si lo prefiere, puedo editar mi publicación para incluir el ejemplo de VB.NET y puede ejecutarlo a través de un convertidor.

Actualizar

Como solicitó el ejemplo de Visual Basic .NET, aquí hay una función que convertiría el archivo en una 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

Dado que el archivo es un archivo de ancho fijo, también deberá emparejarlo con un archivo Schema.ini. En su caso, el archivo .ini se vería así:

[path_name_nere.txt]
Format=FixedLength

Col1=Column1 Text Width 12
Col2=Column2 Text Width 6

Ahora que el archivo se ha convertido en una DataTable, filtraría la DataTable para excluir los duplicados.

1
David 24 oct. 2017 a las 01:13