Compartir a través de


Cómo: Combinar consultas LINQ con expresiones regulares

Actualización: noviembre 2007

En este ejemplo se muestra cómo utilizar la clase Regex para crear una expresión regular para coincidencias más complejas en cadenas de texto. La consulta LINQ hace que sea sencillo aplicar un filtro exactamente a los archivos en los que se desea buscar con la expresión regular y dar forma los resultados.

Ejemplo

Class LinqRegExVB

    Shared Sub Main()

        ' Root folder to query, along with all subfolders.
        ' Modify this path as necessary.
        Dim startFolder As String = "C:\program files\Microsoft Visual Studio 9.0\"

        ' Take a snapshot of the file system.
        Dim fileList As IEnumerable(Of System.IO.FileInfo) = GetFiles(startFolder)

        ' Create a regular expression to find all things "Visual".
        Dim searchTerm As System.Text.RegularExpressions.Regex = _
            New System.Text.RegularExpressions.Regex("Visual (Basic|C#|C\+\+|J#|SourceSafe|Studio)")

        ' Search the contents of each .htm file.
        ' Remove the where clause to find even more matches!
        ' This query produces a list of files where a match
        ' was found, and a list of the matches in that file.
        ' Note: Explicit typing of "Match" in select clause.
        ' This is required because MatchCollection is not a 
        ' generic IEnumerable collection.
        Dim queryMatchingFiles = From afile In fileList _
                                Where afile.Extension = ".htm" _
                                Let fileText = System.IO.File.ReadAllText(afile.FullName) _
                                Let matches = searchTerm.Matches(fileText) _
                                Where (searchTerm.Matches(fileText).Count > 0) _
                                Select Name = afile.FullName, _
                                       Matches = From match As System.Text.RegularExpressions.Match In matches _
                                                 Select match.Value

        ' Execute the query.
        Console.WriteLine("The term " & searchTerm.ToString() & " was found in:")

        For Each fileMatches In queryMatchingFiles
            ' Trim the path a bit, then write 
            ' the file name in which a match was found.
            Dim s = fileMatches.Name.Substring(startFolder.Length - 1)
            Console.WriteLine(s)

            ' For this file, write out all the matching strings
            For Each match In fileMatches.Matches
                Console.WriteLine("  " + match)
            Next
        Next

        ' Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit")
        Console.ReadKey()
    End Sub

    ' Function to retrieve a list of files. Note that this is a copy
    ' of the file information.
    Shared Function GetFiles(ByVal root As String) As IEnumerable(Of System.IO.FileInfo)
        Return From file In My.Computer.FileSystem.GetFiles _
                  (root, FileIO.SearchOption.SearchAllSubDirectories, "*.*") _
               Select New System.IO.FileInfo(file)
    End Function

End Class
class QueryWithRegEx
{
    public static void Main()
    {
        // Modify this path as necessary.
        string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> fileList = GetFiles(startFolder);

        // Create the regular expression to find all things "Visual".
        System.Text.RegularExpressions.Regex searchTerm = 
            new System.Text.RegularExpressions.Regex(@"Visual (Basic|C#|C\+\+|J#|SourceSafe|Studio)");

        // Search the contents of each .htm file.
        // Remove the where clause to find even more matches!
        // This query produces a list of files where a match
        // was found, and a list of the matches in that file.
        // Note: Explicit typing of "Match" in select clause.
        // This is required because MatchCollection is not a 
        // generic IEnumerable collection.
        var queryMatchingFiles =
            from file in fileList
            where file.Extension == ".htm"
            let fileText = System.IO.File.ReadAllText(file.FullName)
            let matches = searchTerm.Matches(fileText)
            where searchTerm.Matches(fileText).Count > 0
            select new
            {
                name = file.FullName,
                matches = from System.Text.RegularExpressions.Match match in matches
                          select match.Value
            };

        // Execute the query.
        Console.WriteLine("The term \"{0}\" was found in:", searchTerm.ToString());


        foreach (var v in queryMatchingFiles)
        {
            // Trim the path a bit, then write 
            // the file name in which a match was found.
            string s = v.name.Substring(startFolder.Length - 1);
            Console.WriteLine(s);

            // For this file, write out all the matching strings
            foreach (var v2 in v.matches)
            {
                Console.WriteLine("  " + v2);
            }
        }

        // Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }

    // This method assumes that the application has discovery 
    // permissions for all folders under the specified path.
    static IEnumerable<System.IO.FileInfo> GetFiles(string path)
    {
        if (!System.IO.Directory.Exists(path))
            throw new System.IO.DirectoryNotFoundException();

        string[] fileNames = null;
        List<System.IO.FileInfo> files = new List<System.IO.FileInfo>();

        fileNames = System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories);
        foreach (string name in fileNames)
        {
            files.Add(new System.IO.FileInfo(name));
        }
        return files;
    }
}

Observe que también se puede consultar el objeto MatchCollection que se devuelve tras una búsqueda RegEx. En este ejemplo, sólo se genera el valor de cada coincidencia en los resultados. Sin embargo, también es posible utilizar LINQ para realizar toda clase de operaciones de filtrado, ordenación y agrupación en esa colección. Dado que MatchCollection es una colección IEnumerable no genérica, es necesario declarar explícitamente el tipo de la variable de rango en la consulta.

Compilar el código

  • Cree un proyecto de Visual Studio orientado a .NET Framework versión 3.5. De manera predeterminada, el proyecto incluye una referencia a System.Core.dll y una directiva using (C#) o una instrucción Imports (Visual Basic) para el espacio de nombres System.Linq. En los proyectos de C#, agregue una directiva using para el espacio de nombres System.IO.

  • Copie este código en el proyecto.

  • Presione F5 para compilar y ejecutar el programa.

  • Presione cualquier tecla para salir de la ventana de consola.

Vea también

Tareas

Cómo generar un XML a partir de archivos CSV

Conceptos

LINQ y cadenas

LINQ y directorios de archivos