# Regex

> Matching, replacing and splitting with regular expressions. A pattern means the same thing wherever your code runs — the platform makes the browser reproduce the server's regex semantics exactly.

<!-- id: function-regex · area: function · stability: stable · html: https://osysharp.com/reference/function/regex/ -->

## Summary        {#summary}

Matching, replacing and splitting with regular expressions. A pattern means the same thing wherever your code runs —
the platform makes the browser reproduce the server's regex semantics exactly, so you never have to think about which
engine evaluated it.

## Signature      {#signature}

```osy syntax
bool     Regex.IsMatch(string input, string pattern)
string   Regex.Replace(string input, string pattern, string replacement)
string[] Regex.Split(string input, string pattern)
```

## Description    {#description}

Osy# regular expressions follow **.NET semantics**, everywhere. That sentence is doing more work than it looks.

Browsers and servers do not natively agree about regular expressions. They are different dialects, and — this is the
dangerous part — they mostly disagree *silently*. The same pattern compiles in both and quietly matches different
things:

| Pattern | Input | .NET | Browser (natively) |
|---|---|---|---|
| `^\d+$` | `٣٤` | matches | does **not** match |
| `^\w+$` | `café` | matches | does **not** match |
| `a$` | `"a\n"` | matches | does **not** match |

`\d` means *any decimal digit* in .NET and *`[0-9]`* in a browser. `\w` means *any word character* in .NET and
*`[A-Za-z0-9_]`* in a browser. And the trap is not in exotic patterns — it is in ordinary ones. `^[A-Z]{3}-\d{4}$`
looks completely safe, and diverges the moment somebody types Arabic-Indic digits.

**You do not have to care.** The compiler rewrites your pattern so the browser reproduces .NET's behaviour, and both
engines are tested against each other on every build. `Regex.IsMatch(name, @"^\w+$")` gives the same answer in an
action running in the browser as it does in a function running on the server.

### When a pattern stays on the server   {#server-only}

A few .NET constructs have no equivalent in a browser at all — atomic groups (`(?>…)`), conditionals (`(?(…)…)`), and
character-class subtraction (`[a-z-[aeiou]]`). And a pattern *built at runtime* from a variable cannot be examined
ahead of time.

In those cases the function simply runs on the server, where .NET evaluates it. Your code is unchanged, the answer is
correct, and the only cost is a round trip. Nothing to configure.

### A note on very complex patterns   {#backtracking}

A pathological pattern can be made to backtrack catastrophically. On the server there is a timeout that stops this. In
a browser there is not — a runaway pattern will hang the tab it is running in. If you are matching against input a user
controls, prefer a simple, anchored pattern.

## Examples       {#examples}

```osy title="validating a code" test app=regex-basics
bool IsOrderCode(string code) {
  return Regex.IsMatch(code, "^[A-Z]{3}-[0-9]{4}$");
}
```

```osy title="masking" test app=regex-basics
string MaskDigits(string s) {
  return Regex.Replace(s, "[0-9]", "*");
}
```

## See also       {#see-also}
- [execution side](https://osysharp.com/reference/function/execution-side/) — where a function runs, and why a regex does not force the choice
