在 C# 中搜尋字串

小提示

本文屬於 基礎部分, 適合已經至少懂一種程式語言並正在學習 C# 的開發者。 如果你是程式新手,建議先從 入門 教學開始。

來自另一種語言? C# 的 string 方法,例如 ContainsStartsWithIndexOf,對應於 Java 的 String 與 JavaScript 的 String.prototype 中的平行方法。 主要差異在於,某些 C# 搜尋預設會採用 序數方式、區分大小寫的 比較。 另一些則是遵循當前文化的語義。 對於面向使用者的搜尋,你可能想傳遞一個 StringComparison 數值。

課程 String 包含回答兩個日常問題的方法:

更複雜的搜尋與替換演算法可用正則表達式建構。 欲了解更多關於正則表達式及其他字串操作的資訊,請參閱語言參考文章中的 字串操作

檢查字串是否包含文字

使用 ContainsStartsWith,或 EndsWith 用來測試子字串的存在:

string factMessage = "Extension methods have all the capabilities of regular static methods.";

// Write the string and include the quotation marks.
Console.WriteLine($"\"{factMessage}\"");

// Default comparisons are case sensitive.
bool containsSearchResult = factMessage.Contains("extension");
Console.WriteLine($"""Contains "extension"? {containsSearchResult}""");

// For user-facing searches, pass a StringComparison value to control case and culture.
bool ignoreCaseSearchResult = factMessage.StartsWith("extension", StringComparison.CurrentCultureIgnoreCase);
Console.WriteLine($"""Starts with "extension"? {ignoreCaseSearchResult} (ignoring case)""");

bool endsWithSearchResult = factMessage.EndsWith(".", StringComparison.Ordinal);
Console.WriteLine($"Ends with '.'? {endsWithSearchResult}");
// => "Extension methods have all the capabilities of regular static methods."
// => Contains "extension"? False
// => Starts with "extension"? True (ignoring case)
// => Ends with '.'? True

這些方法預設會採用 區分大小寫的序數 比較。 若要接受使用者輸入或忽略顯示文字的大小寫,請傳遞 StringComparisonStringComparison.CurrentCultureIgnoreCaseStringComparison.OrdinalIgnoreCase的值。

當您搜尋單一字元時,請使用 Containschar 多載。 它可避免配置單一字元字串,而且寫法更直接:

string path = "/usr/local/bin";
bool hasSlash = path.Contains('/');
Console.WriteLine($"Path contains '/': {hasSlash}");
// => Path contains '/': True

定位文字的位置

IndexOf 回傳子字串(或字元)首次出現時的零為基礎索引,並 LastIndexOf 回傳最後一次出現的索引。 當搜尋文字不存在時,兩者都會回傳 -1 。 將它們結合起來,擷取兩個標記之間的文字:

string factMessage = "Extension methods have all the capabilities of regular static methods.";

Console.WriteLine($"\"{factMessage}\"");

// Extract the text between the first and last occurrence of "methods".
int first = factMessage.IndexOf("methods") + "methods".Length;
int last = factMessage.LastIndexOf("methods");
string between = factMessage.Substring(first, last - first);
Console.WriteLine($"""Substring between "methods" and "methods": '{between}'""");
// => "Extension methods have all the capabilities of regular static methods."
// => Substring between "methods" and "methods": ' have all the capabilities of regular static '

當你需要每次出現而非第一次或最後一次時,可以重複運算,將前一個結果加上一作為 startIndex 參數,或改用正則表達式。

選擇適當的比較方式

大多數搜尋超載會接受一個可選 StringComparison 值。 根據你搜尋的資料類型來選擇:

  • 如果你在搜尋識別碼、檔案路徑、協定標記或其他機器定義的東西,請使用 Ordinal
  • 如果你搜尋的是相同類型的機器定義資料,但想要大小寫不區分,請使用 OrdinalIgnoreCase
  • 如果你在搜尋使用者可見的文字,且該區域的規則應該適用,請使用 CurrentCulture
  • 如果你搜尋相同的使用者可見文字,且想忽略大小寫,請使用 CurrentCultureIgnoreCase
  • 如果您要搜尋必須在任何機器與文化設定下都得到相同比較結果的持續保存資料,請使用 InvariantCulture(很少需要這麼做)。

序數比較是最快的選擇,也是非自然語言文本的正確預設。 文化意識比較速度明顯較慢,且可能產生令人驚訝的結果。 例如,在某些文化中,小寫 i 與大寫 I 不相符。請僅將其保留用於使用者針對一般文字內容進行的搜尋。

如需深入了解區分文化特性的比較,請參閱 比較字串的最佳做法

另請參閱