Regular expressions - eevdriet/obsidian-anki GitHub Wiki
A regular expression (regex) can be used to define how notes are exported from Obsidian. Each regex should consist of at least one capture group that capture the value of a field of the note. Alternatively, you can also use templates.
Introduction
Regular expressions allows for a very flexible way to search through text for something that you're looking for. If you're not yet familiar with regular expressions, I recommend
- RegExInfo for initial learning and as documentation source
- regex101 for testing whether your regexes work as intended
To give one example that I like to use to define a Basic
note with a Front
and Back
field:
^([\w\s]+) -> ([\w\s]+) #note/basic$
This regex can be broken down as follows:
Element | Meaning |
---|---|
^ ... $ |
The note is placed on a single line of text |
([\w\s]+) |
One or more words separated by white space, which resembles the Front |
-> |
Arrow to separate the Front and Back |
([\w\s]+) |
One or more words separated by white space, which resembles the Back |
#note/basic |
Tag to indicate a basic note |
Capture groups
If you've used a template before, you can think of a capture group like a field pattern.
In our example above, there a 2 capture groups which are delimited by ()
with whatever you're trying to capture in between.
The idea is to set the note's fields from whatever is captured by these groups.
When the regex is applied, the 1st group sets the 1st field, the 2nd group sets the 2nd field and so on.
One caveat is that at least one group needs to be non-empty for a note to be recognized in text.
Consider again the regex for Basic
notes
^([\w\s]*) -> ([\w\s]*) #note/basic$
Below you can see how the regex works and what text its groups capture:
el gato -> the cat #note/basic <!-- OK: `Front` is captured by "el gato" and `Back` is captured by "the cat" -->
el gato -> #note/basic <!-- OK: `Front` is captured by "el gato" and `Back` is not captured -->
-> the cat #note/basic <!-- OK: `Front` is not captured and `Back` is captured by "the cat" -->
#note/basic <!-- ERROR: `Front` and `Back` are not captured as both groups are empty -->
Field order
One downside to setting the fields in order of the capture groups is that you have to define a capture group for every field in the regex.
Consider a note type Country
that has the following fields:
Name
Capital
Language
Currency
Now suppose you want your notes to set the Name
and Currency
, but you don't care about the Capital
and Language
.
Setting the fields in order, you'd have to define empty capture groups ()
just to have the 4th group set the Currency
.
This is cumbersome, especially if you have note types with many fields.
Instead you can define a custom field order such that any group can set any field:
Now you can use the regex
^(\w\s)+ pays with (\w\s)+ #note/country$
for your Country
notes, where
Name
andCurrency
are set from the 1st and 2nd capture groups respectivelyCapital
andLanguage
are not set at all
Examples
To get an understanding of how regular expressions work in practice, below are some examples. These highlight what errors might come up when defining your own and when notes are or are not matched to a given regex.
Common errors
The template can never be empty
The template should include {{Front}}
, {{Back}}
or {{Fields}}
to make it valid
The template includes invalid pattern {{Middle}}
, which should be removed
Matching notes
For these examples, we will use the Basic
note type.
- First consider the following template:
Below are some notes defined in the text and whether they match the template.Deck: {{Deck}} {{Tags}} {{Front}} -> {{Back}}
Deck: Language::Spanish <!-- MATCH: note exported with --> <!-- - {{Deck}} set as "Language::Spanish" and {{Tags}} not set --> el gato -> the cat <!-- - {{Front}} set as "el gato" and {{Back}} set as "the cat" --> Deck: <!-- MATCH: note exported with --> language/spanish, language/word <!-- - {{Deck}} not set and {{Tags}} set as ["language/spanish", "language/word"] --> el gato -> <!-- - {{Front}} set as "el gato" and {{Back}} not set --> Deck: <!-- MATCH: note exported with --> <!-- - {{Deck}} and {{Tags}} not set --> -> the cat <!-- - {{Front}} not set and {{Back}} set as "the cat" --> Deck: Language::Spanish <!-- NO MATCH: literal text "->" in the template is not matched --> language/spanish, language/word el gato - the cat