C# split string
last modified November 6, 2026
In this article we show how to split strings in C# with the
String.Split and Regex.Split methods, and how to
split without allocations using spans.
The String.Split method divides a string into an array of
substrings at the positions of one or more delimiters, which can be characters
or strings. For more complex patterns, Regex.Split splits at the
matches of a regular expression.
Split(char separator, StringSplitOptions options = None) Split(char separator, int count, StringSplitOptions options = None) Split(params char[]? separator) Split(params ReadOnlySpan<char> separator) Split(char[]? separator, int count) Split(char[]? separator, StringSplitOptions options) Split(char[]? separator, int count, StringSplitOptions options) Split(string? separator, StringSplitOptions options = None) Split(string? separator, int count, StringSplitOptions options = None) Split(string[]? separator, StringSplitOptions options) Split(string[]? separator, int count, StringSplitOptions options)
In .NET 10, String.Split has eleven overloads. They differ in the
type of the delimiter, the maximum number of substrings, and the
StringSplitOptions flags.
Splitting by a single character
The basic use of Split divides a sentence into words at the
spaces.
string text = "There is an old hawk in the sky";
string[] words = text.Split(' ');
Console.WriteLine($"{words.Length} words");
foreach (string word in words)
{
Console.WriteLine(word);
}
The program splits a sentence into words and prints them.
string[] words = text.Split(' ');
The method returns a new array of strings. The delimiters are not part of the substrings.
$ dotnet run 8 words There is an old hawk in the sky
StringSplitOptions
Consecutive delimiters, or a delimiter at the beginning or end of the string,
produce empty strings. The StringSplitOptions flags control
this.
None- keep all substrings, including empty onesRemoveEmptyEntries- omit empty substringsTrimEntries- trim whitespace from each substring
string text = " falcon, owl,, eagle , hawk ,";
string[] a = text.Split(',');
Console.WriteLine(string.Join("|", a));
string[] b = text.Split(',', StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(string.Join("|", b));
string[] c = text.Split(',', StringSplitOptions.TrimEntries);
Console.WriteLine(string.Join("|", c));
string[] d = text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
Console.WriteLine(string.Join("|", d));
We split a messy comma-separated list with each combination of options. The substrings are joined with a vertical bar to make the spaces and empty entries visible.
string[] b = text.Split(',', StringSplitOptions.RemoveEmptyEntries);
The empty strings between the two commas and after the last comma are removed, but the substrings keep their spaces.
string[] c = text.Split(',', StringSplitOptions.TrimEntries);
The spaces are trimmed, but empty entries remain.
string[] d = text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
The options are flags and can be combined. With both, entries that become empty after trimming are removed too. This is the usual choice for parsing user input.
$ dotnet run falcon| owl|| eagle | hawk | falcon| owl| eagle | hawk falcon|owl||eagle|hawk| falcon|owl|eagle|hawk
Splitting by multiple characters
Split accepts several delimiter characters. Called without
arguments, it splits at whitespace characters.
string text = "falcon;eagle,forest sky;cloud,water rock";
string[] words = text.Split([',', ';', ' ']);
Console.WriteLine(string.Join("|", words));
string messy = "There are\t\tmany clouds\nin the sky";
string[] parts = messy.Split();
Console.WriteLine(string.Join("|", parts));
string[] clean = messy.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(string.Join("|", clean));
We split a string at commas, semicolons, and spaces, and then a string with mixed whitespace.
string[] words = text.Split([',', ';', ' ']);
The collection expression creates the separators. The string is split wherever any of the characters occurs.
string[] parts = messy.Split();
Without separators, Split uses all whitespace characters,
including tabs and newlines. Consecutive whitespace still produces empty
entries.
string[] clean = messy.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
To split at any whitespace and remove empty entries, we pass null
as the separator array. The cast selects the right overload.
$ dotnet run falcon|eagle|forest|sky|cloud|water|rock There|are||many||clouds|in|the|sky There|are|many|clouds|in|the|sky
Limiting the number of substrings
The count parameter sets the maximum number of substrings. The
last substring contains the rest of the string, including the remaining
delimiters.
string text = "falcon,eagle,forest,sky,cloud,water,rock,wind";
string[] words = text.Split(',', 4);
Array.ForEach(words, Console.WriteLine);
string header = "Content-Type: text/html; charset=utf-8";
string[] kv = header.Split(':', 2, StringSplitOptions.TrimEntries);
Console.WriteLine($"name: {kv[0]}, value: {kv[1]}");
We split a list into at most four parts and an HTTP header into a name and a value.
string[] kv = header.Split(':', 2, StringSplitOptions.TrimEntries);
The limit of two parts splits only at the first colon. This is useful for name-value pairs whose values may contain the delimiter.
$ dotnet run falcon eagle forest sky,cloud,water,rock,wind name: Content-Type, value: text/html; charset=utf-8
Splitting by strings
The delimiter can be a string or an array of strings.
string birds = "hawkxxowlxxvulturexxeagle";
Console.WriteLine(string.Join(", ", birds.Split("xx")));
string text = "line one\r\nline two\nline three\r\n";
string[] lines = text.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
Console.WriteLine($"[{line}]");
}
string data = "red AND green OR blue AND yellow";
string[] colors = data.Split([" AND ", " OR "], StringSplitOptions.None);
Console.WriteLine(string.Join(", ", colors));
We split at a two-character delimiter, at Windows and Unix line endings, and at two keywords.
string[] lines = text.Split(["\r\n", "\n"], StringSplitOptions.RemoveEmptyEntries);
At each position, the separators are tried in the order of the array. The
order matters only when one separator is a prefix of another; for instance,
"abcd".Split(["b", "bc"], ...) gives "a" and "cd", while
["bc", "b"] gives "a" and "d". Here the two line endings start
with different characters, so the order does not matter.
$ dotnet run hawk, owl, vulture, eagle [line one] [line two] [line three] red, green, blue, yellow
Parsing structured data
Splitting is often the first step of parsing simple text formats.
string csv = """
John Doe,gardener,1230
Roger Roe,driver,1460
Lucy Novak,teacher,2100
""";
var users = new List<User>();
foreach (string line in csv.Split('\n', StringSplitOptions.RemoveEmptyEntries))
{
string[] f = line.Split(',', StringSplitOptions.TrimEntries);
users.Add(new User(f[0], f[1], int.Parse(f[2])));
}
users.ForEach(Console.WriteLine);
string conn = "Server=localhost;Port=5432;Database=testdb;User Id=admin";
Dictionary<string, string> settings = conn
.Split(';', StringSplitOptions.RemoveEmptyEntries)
.Select(pair => pair.Split('=', 2))
.ToDictionary(kv => kv[0], kv => kv[1]);
Console.WriteLine($"{settings["Database"]} on {settings["Server"]}:{settings["Port"]}");
record User(string Name, string Occupation, int Salary);
We parse CSV lines into records and a connection string into a dictionary.
foreach (string line in csv.Split('\n', StringSplitOptions.RemoveEmptyEntries))
{
string[] f = line.Split(',', StringSplitOptions.TrimEntries);
users.Add(new User(f[0], f[1], int.Parse(f[2])));
}
First we split the text into lines, then each line into fields. Real CSV files may contain quoted fields with commas; use a CSV library such as CsvHelper for those.
Dictionary<string, string> settings = conn
.Split(';', StringSplitOptions.RemoveEmptyEntries)
.Select(pair => pair.Split('=', 2))
.ToDictionary(kv => kv[0], kv => kv[1]);
The connection string is split into pairs, each pair into a key and a value, and LINQ builds a dictionary.
$ dotnet run
User { Name = John Doe, Occupation = gardener, Salary = 1230 }
User { Name = Roger Roe, Occupation = driver, Salary = 1460 }
User { Name = Lucy Novak, Occupation = teacher, Salary = 2100 }
testdb on localhost:5432
Splitting with Regex.Split
The Regex.Split method splits a string at the matches of a
regular expression. It has three static and three instance overloads.
using System.Text.RegularExpressions;
string text = "There are\t\t many clouds in the \n sky.";
string[] words = Regex.Split(text, @"\s+");
Console.WriteLine(string.Join("|", words));
string expr = "12+5-3*2";
Console.WriteLine(string.Join(" ", Regex.Split(expr, @"[+\-*]")));
Console.WriteLine(string.Join(" ", Regex.Split(expr, @"([+\-*])")));
string name = "parseHtmlDocumentToXml";
string[] parts = Regex.Split(name, @"(?<=[a-z])(?=[A-Z])");
Console.WriteLine(string.Join(" ", parts));
string dates = "2026-11-06, 2025/04/20; 2024.01.19";
foreach (string d in Regex.Split(dates, @"[,;]\s*"))
{
Console.WriteLine(string.Join(" ", Regex.Split(d, @"[-/.]")));
}
We split at runs of whitespace, at arithmetic operators, at the word boundaries of a camelCase identifier, and at various date separators.
string[] words = Regex.Split(text, @"\s+");
The \s+ pattern matches one or more whitespace characters, so
consecutive spaces and tabs produce no empty entries.
Console.WriteLine(string.Join(" ", Regex.Split(expr, @"([+\-*])")));
If the pattern contains a capturing group, the captured text is included in the result. This keeps the operators between the numbers.
string[] parts = Regex.Split(name, @"(?<=[a-z])(?=[A-Z])");
Lookbehind and lookahead assertions match an empty position between a lowercase and an uppercase letter. No characters are removed. For more on patterns, see the C# regular expressions tutorial.
$ dotnet run There|are|many|clouds|in|the|sky. 12 5 3 2 12 + 5 - 3 * 2 parse Html Document To Xml 2026 11 06 2025 04 20 2024 01 19
Splitting spans without allocations
Since .NET 9, the MemoryExtensions.Split method splits a
ReadOnlySpan<char> lazily. Instead of an array of new
strings, it returns the Range of each part, so no memory is
allocated.
string line = "falcon,eagle,forest,sky,cloud";
ReadOnlySpan<char> span = line;
foreach (Range r in span.Split(','))
{
ReadOnlySpan<char> word = span[r];
Console.WriteLine($"{word} ({word.Length})");
}
string nums = "4 8 15 16 23 42";
int sum = 0;
foreach (Range r in nums.AsSpan().Split(' '))
{
sum += int.Parse(nums.AsSpan(r));
}
Console.WriteLine($"sum: {sum}");
We print the words of a line and sum numbers from a string.
foreach (Range r in span.Split(','))
{
ReadOnlySpan<char> word = span[r];
The enumerator yields ranges; slicing the span with a range gives the part.
sum += int.Parse(nums.AsSpan(r));
Many parsing methods accept spans, so we parse the numbers without creating any substrings. This matters in hot paths that process large amounts of text.
$ dotnet run falcon (6) eagle (5) forest (6) sky (3) cloud (5) sum: 108
Joining strings
The string.Join method is the inverse of Split. It
concatenates elements with a separator.
List<string> words = ["falcon", "wood", "sky", "water"];
Console.WriteLine(string.Join(",", words));
Console.WriteLine(string.Join(" - ", words));
Console.WriteLine(string.Join('|', 1, 2, 3, 4));
string text = "falcon wood sky water";
string normalized = string.Join(' ', text.Split(' ', StringSplitOptions.RemoveEmptyEntries));
Console.WriteLine(normalized);
We join words with different separators and normalize whitespace with a
combination of Split and Join.
string normalized = string.Join(' ', text.Split(' ', StringSplitOptions.RemoveEmptyEntries));
Splitting with RemoveEmptyEntries and joining with a single space
collapses runs of spaces.
$ dotnet run falcon,wood,sky,water falcon - wood - sky - water 1|2|3|4 falcon wood sky water
Source
Divide strings using String.Split
In this article we have split strings in C# with String.Split,
Regex.Split, and span splitting.
Author
List all C# tutorials.