如何:合併 LINQ 查詢與規則運算式
這個範例顯示如何使用 Regex 類別 (Class) 建立規則運算式 (Regular Expression),來進行文字字串的較複雜比對。 LINQ 查詢可以使用規則運算式輕鬆地篩選出您想要搜尋的檔案,以及塑造結果。
範例
Class LinqRegExVB
Shared Sub Main()
' Root folder to query, along with all subfolders.
' Modify this path as necessary so that it accesses your Visual Studio folder.
Dim startFolder As String = "C:\program files\Microsoft Visual Studio 9.0\"
' One of the following paths may be more appropriate on your computer.
'string startFolder = @"c:\program files (x86)\Microsoft Visual Studio 9.0\";
'string startFolder = @"c:\program files\Microsoft Visual Studio 10.0\";
'string startFolder = @"c:\program files (x86)\Microsoft Visual Studio 10.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 (matches.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 so that it accesses your version of Visual Studio.
string startFolder = @"c:\program files\Microsoft Visual Studio 9.0\";
// One of the following paths may be more appropriate on your computer.
//string startFolder = @"c:\program files (x86)\Microsoft Visual Studio 9.0\";
//string startFolder = @"c:\program files\Microsoft Visual Studio 10.0\";
//string startFolder = @"c:\program files (x86)\Microsoft Visual Studio 10.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 matchedValues!
// This query produces a list of files where a match
// was found, and a list of the matchedValues 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 matches.Count > 0
select new
{
name = file.FullName,
matchedValues = 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.matchedValues)
{
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;
}
}
請注意,您也可以查詢 RegEx 搜尋所傳回的 MatchCollection 物件。 在這個範例的結果中,只會產生每個相符項目的值。 不過,您也可以使用 LINQ 對該集合執行任何種類的篩選、排序和分組。 因為 MatchCollection 是非泛型 IEnumerable 集合,所以您需要在查詢中明確陳述範圍變數的型別。
編譯程式碼
建立一個以 .NET Framework 3.5 版為目標的 Visual Studio 專案。 根據預設,專案有 System.Core.dll 的參考,以及 System.Linq 命名空間的 using 指示詞 (C#) 或 Imports 陳述式 (Visual Basic)。 請在 C# 專案中,加入 System.IO 命名空間的 using 指示詞。
請將這段程式碼複製到您的專案,
按 F5 編譯和執行程式。
按任何鍵離開主控台視窗。