Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Function

Text.Like

Text.Like(s, pattern) -> bool — wildcard match: % any run, _ one character, \ escapes

Matches a string against a wildcard pattern, where % stands for any run of characters and _ for exactly one. It is the only wildcard search in the language — the instance methods Contains, StartsWith and EndsWith are literal — and it is the one that a database can answer with an index. It gives the same answer in the browser, in a function body, and pushed down into a query.

stable1 example compiled by CIfunctiontextquerysearch

Summary#

Text.Like(s, pattern) tests a string against a wildcard pattern. It is the deliberate opposite of Contains, StartsWith, EndsWith: there the argument is data, here it is a pattern.

Signature#

Text.Like(<string>, <string>) -> bool

Description#

The pattern#

in the patternmatches
%any run of characters, including none
_exactly one character
\% \_ \\a literal %, _ or \
anything elseitself
Text.Like(code, "RUSH-%")        // begins with RUSH-
Text.Like(code, "%-2026")        // ends with -2026
Text.Like(code, "A_-%")          // A, then any one character, then "-", then anything
Text.Like(label, @"50\% off")    // a LITERAL percent sign

Why it is not a method on the string#

s.Contains(x), s.StartsWith(x) and s.EndsWith(x) are literal searches — a % in the argument is a percent sign. Text.Like is the wildcard one. They are spelled differently on purpose: the difference between "find this text" and "find things shaped like this" should be visible where you read the call, not something you have to remember. C# has no Like at all, and EF Core makes the same split for the same reason (EF.Functions.Like, never a method on string).

It is case-sensitive#

Text.Like("ACME Ltd", "acme%") is false. To ignore case, lower both sides:

Text.Like(c.Name.ToLower(), "acme%")

Inside a query, it can use an index#

This is the practical reason it exists. Contains becomes a substring search that has to look at every row; a Like whose pattern is anchored at the front ("RUSH-%") can be answered from a btree index on the column. A pattern that starts with % cannot — it has nothing to seek to — so prefer an anchored pattern when the table is large.

A pattern that ends with a bare \#

A trailing escape character escapes nothing, so such a pattern can never match anything. When the pattern is written out in the source it is a compile error; double it (\\) if you meant a literal backslash.

One answer, wherever it runs#

The same call gives the same result in a browser action, in a function body on the server, and compiled into SQL — the three implementations are tested against each other over a corpus that includes %, _, \, newlines and characters outside the Basic Multilingual Plane.

Examples#

entity Product { string Code; string Name; }

List<Product> RushCodes() {
  return Product.Where(p => Text.Like(p.Code, "RUSH-%")).ToList();   // anchored: an index can serve it
}

bool LooksLikeABatch(string code) {
  return Text.Like(code, "B__-____");        // B, two characters, a dash, four characters
}

bool MentionsAPercentage(string label) {
  return Text.Like(label, @"%\%%");          // contains a literal percent sign
}

See also#

Related

Contains, StartsWith, EndsWith

Tests whether a string contains, begins with, or ends with another string. The match is case-sensitive and literal —…

Regex

Match, replace, split and CAPTURE with regular expressions — the C#-faithful System.Text.RegularExpressions spelling…

execution side

Where a function runs. Osy# infers it from the body: a function that reads data runs on the server, a function that…