# Regular Expressions
## Introduction
> [!released]
Introduced in Tasks 1.12.0.
[Regular expression](https://en.wikipedia.org/wiki/Regular_expression) ("regex") searches are a powerful alternative to the simple `includes` and `does not include` searches.
### Take Care
> [!warning]
> Regular expression (or 'regex') searching is a powerful but advanced feature that requires thorough knowledge in order to use successfully, and not miss intended search results.
It is easy to write a regular expression that looks like it is correct, but which uses a special character that completely changes the meaning of the search string.
For example, `\d` does **not** match the **two** characters `\d`, it matches any **one** of the following characters: `0123456789`.
This documentation gives only a brief overview of the facility, with a few motivating examples, and then links to other resources, for thorough treatment.
Having said that, regex searches are a valuable tool, used in many other tools, and time invested in learning about them can pay off well in future, in many other tools and scenarios.
## Basics
The components of a regex search filter are:
1. The field name, for example `description` or `path`
2. Either `regex matches` or `regex does not match`
3. The search pattern, inside a pair of forwards slashes, for example `/pc_abigail|pc_edwina|at_work/`
- That pattern searches for `pc_abigail`, `pc_edwina` or `at_work`, without the need to create a boolean combination of three separate filters
4. Optionally, an extra [flag](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags) at the end, such as `i`, that can change the meaning of the expression
- Note that many of the allowed flags are not relevant in the Tasks context, because there are no multi-line searches or global searches, for example.
Case-sensitive example, showing the components:
```text
description regex matches /pc_abigail|pc_edwina|at_work/
^1 ^2 ^3
```
Case-INsensitive example, showing the components:
```text
description regex matches /pc_abigail|pc_edwina|at_work/i
^1 ^2 ^3 ^4
```
## Notes
- Regex searches are **case-sensitive**, unlike the simpler `includes` and `does not include`
- A regex search can be made **insensitive** by appending a `i` flag after the closing `/`, for example: `/I aM cAsE INsensitive because of the LiTle i after the closing slash/i`
- Tasks does not support multi-line regex searches, as each task is a single line.
## Escaping special characters
To search for any of the characters `[ \ ^ $ . | ? * + ( )` literally in Tasks, you should put a `\` character before each of them.
This is called 'escaping'. See [Escaping, special characters](https://javascript.info/regexp-escaping).
See the next section for the meaning of some of these characters.
> [!Tip]
> Since Tasks 4.3.0, it is no longer necessary to escape `/` characters as `\/`, although searches will still work if you do escape them.
>
> So these two searches are now identical, and will both search for tasks in any folder that contains `Root/Sub-Folder/Sub-Sub-Folder` anywhere:
>
> ```task
> folder regex matches /Root/Sub-Folder/Sub-Sub-Folder/
> folder regex matches /Root\/Sub-Folder\/Sub-Sub-Folder/
> ```
## Explain: inspecting regular expressions
> [!released]
> Introduced in Tasks 4.3.0.
To see how Tasks interpreted your regular expression, you can add an `explain` line to the query.
For example, the results of this query:
<!-- snippet: DocsSamplesForExplain.test.explain_regular_expression.approved.query.text -->
```text
explain
path regex matches /^Root/Sub-Folder/Sample File\.md/i
```
<!-- endSnippet -->
will have this extra text in an [[Explaining Queries|explanation]] at the start:
<!-- snippet: DocsSamplesForExplain.test.explain_regular_expression.approved.explanation.text -->
```text
Explanation of this Tasks code block query:
path regex matches /^Root/Sub-Folder/Sample File\.md/i =>
using regex: '^Root\/Sub-Folder\/Sample File\.md' with flag 'i'
No grouping instructions supplied.
No sorting instructions supplied.
```
<!-- endSnippet -->
The use of apostrophes (`'`) rather than forward slashes (`/`) in the explanation is intended to emphasise that the delimiting slashes in the query are not included in the search strings.
## Special characters
If using regex searches, it is important to be aware of the available special characters for several reasons:
1. They enable complex queries to written in simple ways
2. They can cause confusing results or broken searches, if not "escaped" in the search.
Here are a few examples of the [many special characters](https://javascript.info/regexp-escaping):
- `.` matches any character
- `[...]` means search for any of the characters in the square brackets.
- For example, `[aeiou]` will match any of an `a`, `e`, `i`, `o` or `u`.
- See [Sets and ranges \[...\]](https://javascript.info/regexp-character-sets-and-ranges)
- Start and end
- `^` matches the start of the string (but when `[^inside brackets]`, it means "not")
- `
matches the end of the string
- See [Anchors: string start ^ and end $](https://javascript.info/regexp-anchors)
- `|` is an `OR` in regular expressions
- See [Alternation (OR) \|](https://javascript.info/regexp-alternation)
- `\` adds special meaning to some characters. For example:
- `\d` matches one digit, from 0 to 9
- `\D` matches character that is not a digit
- See [Character classes](https://javascript.info/regexp-character-classes)
For a thorough, clear introduction to all the options, see [Regular expressions](https://javascript.info/regular-expressions) at JavaScript.info.
## Important links
Learning resources:
- [Regular expressions](https://javascript.info/regular-expressions) at JavaScript.info
- [Regex Tutorial](https://regexone.com/)
- [Regex Cheat Sheet](https://www.rexegg.com/regex-quickstart.html)
Online tools for experimenting with - and testing - regular expressions:
- [Regex Testing Tool: regex101](https://regex101.com/): Select the flavor 'ECMAScript (JavaScript)'
Implementation details:
- Implemented using [JavaScript's RegExp implementation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
- Supports [JavaScript RegExp Flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags), although not all of them are relevant in this context.
## Known limitations
Please be aware of the following limitations in Tasks' implementation of regular expression searching:
- [Lookahead and Lookbehind](https://www.regular-expressions.info/lookaround.html) searches are untested, and are presumed not to work on Apple mobile devices, or to cause serious performance problems with slow searches.
## Regular expression examples
Below are some example regex searches, to give some ideas of what can be done.
There are some more examples in the [Tasks-Demo sample vault](https://github.com/obsidian-tasks-group/obsidian-tasks/tree/main/resources/sample_vaults/Tasks-Demo), in the file [Regular Expression Searches](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/resources/sample_vaults/Tasks-Demo/Filters/Regular%20Expression%20Searches.md).
### Searching the start of a field
Find tasks whose description begins with Log, exact capitalisation:
```text
description regex matches /^Log/
```
---
Find tasks whose description begins with Log, ignoring capitalisation
```text
description regex matches /^Log/i
```
### Finding empty fields
I want to find tasks that have no description, perhaps because they were created from a template:
```text
description regex matches /^$/
```
I want to exclude tasks with no description:
```text
description regex does not match /^$/
```
How this works: in regular expressions, `/^$/` matches text where there is nothing between the start and the end.
### Finding tasks that are waiting
I want to find tasks that are waiting for something else. But 'waiting' can be spelled in several different ways:
```text
description regex matches /waiting|waits|wartet/i
```
### Finding times
Find tasks containing a time in the description - simple version. This matches invalid times, such as `99:99`, as `\d` means 'any digit'.
```text
description regex matches /\d\d:\d\d/
```
---
Find tasks containing a time in the description. This is more precise than the previous example, thanks to specifying which digits are allowed in each position.
```text
description regex matches /[012][0-9]:[0-5][0-9]/
```
### Finding sub-tags
Suppose you wanted to search for tags of this form: `#tag/subtag3/subsubtag5`, where the `3` and the `5` are allowed to be any single digit.
- We can use either `[0-9]` or `\d` to match a single digit.
- To find a sub-tag, any `/` characters must be 'escaped' to prevent them truncating the rest of the search pattern.
Escaping the `/` leads us to this instruction, which we have made case-insensitive to find capitalised tags too:
```text
tags regex matches /#tag\/subtag[0-9]\/subsubtag[0-9]/i
```
### Finding short tags
Suppose you wanted to search for tasks with a very short tag in: `#t`, and to not match tags like `#task` and `#t/subtag`.
```text
tag regex matches /#t$/i
```
The `
prevents there being any more characters in the tag after the search pattern.
The `i` makes the search case-insensitive.