Recursive AI

Split text into sentences in C#

OneNLP is a free, open-source natural language processing library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Split sentences with Unicode rules and language-specific abbreviation data.

Terminal
dotnet add package RecursiveAI.OneNlp

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

C#
using RecursiveAI.OneNlp;
 
var sentences = Nlp.Sentences(
    "Dr. Smith arrived. We left!");
foreach (var sentence in sentences)
    Console.WriteLine(sentence.Text);

The snippet prints one sentence per line.

Text
Dr. Smith arrived.
We left!

Unzip the example, then dotnet run.

The full program

The download’s Program.cs uses the same visible input as the snippet at the top. No input files are needed.

The download’s Program.cs is the snippet above.

dotnet run prints:

Text
Dr. Smith arrived.
We left!

Null input raises ArgumentNullException; input beyond Nlp.MaxLength raises ArgumentOutOfRangeException.

Variations

Keep sentence offsets. The ranges locate each sentence in the original string. This is a standalone replacement for Program.cs.

C#
using RecursiveAI.OneNlp;
 
foreach (var sentence in Nlp.Sentences("Hello. Goodbye!"))
    Console.WriteLine($"{sentence.StartChar}..{sentence.EndChar}: {sentence.Text}");
Text
0..6: Hello.
7..15: Goodbye!

The short answer

Call Nlp.Sentences(text) and read each span’s Text. The core package is RecursiveAI.OneNlp, the library installed above. On its own, it splits sentences using rules rather than a trained language model. The example keeps Dr. inside the first sentence and prints Dr. Smith arrived. followed by We left!. No extra model package or model file is needed for this example.

How do I split text into sentences in C#?

Use sentence spans rather than deleting punctuation and attempting to reconstruct it later. The span holds the original sentence text, including punctuation and spaces between its tokens. The complete program above needs only a string. Its variation also prints StartChar and EndChar when the next stage needs positions for highlighting or extraction.

These character offsets refer to the original .NET string and use an exclusive end. The span also has token indexes, Start and End, which are not interchangeable with character positions. Preserve the original string if you save the ranges. Trimming, rewriting punctuation or normalizing whitespace can shift positions and requires fresh segmentation.

The segmentation documentation defines the core behavior: Unicode sentence boundaries are snapped to token starts, and language data can suppress boundaries after listed abbreviations. English examples include Dr. and Mr.. Abbreviations that can themselves end sentences remain ambiguous; the documentation specifically leaves a full stop after U.S. to Unicode’s rules.

This path is rule-based, not a promise to infer missing punctuation. The documented rules do not break before a lowercase word after a full stop, and they do not divide unpunctuated web text into inferred sentences. If the input is chat messages, OCR or fragments, inspect representative results before assuming each returned span corresponds to a grammatical sentence.

Add a model package, such as RecursiveAI.OneNlp.Models.English, when you need model-based sentence splitting or other annotations such as names and dictionary forms. That model learns sentence boundaries from training text and can return different boundaries from the rules used here; see the language model documentation. To reproduce this example’s results, use only RecursiveAI.OneNlp, as the download does.

What does split() do in C#?

String.Split divides a string using separators you specify. It does not by itself know whether a period ends a sentence or belongs to a title, abbreviation or number. Splitting at every period would discard information the sentence segmenter uses, and it would still need separate handling for exclamation points and question marks.

Use delimiter splitting when the input format defines a delimiter. Splitting on newlines can be appropriate for line-oriented records, but a paragraph may contain several sentences and one sentence may cross a line break. Line splitting and sentence segmentation answer different questions.

For a downstream task, decide whether you need strings alone or ranges into a larger document. Strings are convenient for display; ranges retain the relationship to the source. OneNLP returns spans so the same result can serve either use without guessing where a sentence occurred later.

All onenlp recipes