# How to use Discourse regexes with watched words?

**URL:** https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522
**Category:** Support
**Created:** [April 24, 2017, 9:25pm UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522 "2017-04-24T21:25:19Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![rizka](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rizka/32/79717_2.png) [@rizka](https://meta.discourse.org/u/rizka)
#### Post date: [April 24, 2017, 9:25pm UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/1 "2017-04-24T21:25:19Z")

</div>

I’ve worked on censoring the most vulgar swear words with regular expressions today. Why regexes? Well, in Finnish and other Uralic languages like Hungarian and Estonian words are inflected. A single swear word could have maybe thousands of mutations, which is why it is awesome to have the ability to use regex patterns. It is also no coincidence that it was another Finn who proposed this originally.

> [@Support for wildcards in word censoring](https://meta.discourse.org/t/support-for-wildcards-in-word-censoring/26866):
>
> I don’t know if anyone actually uses this for other than fun but due to inflection it would be nice to be able to use wildcards when adding censored words.

I need some quick advice about which regex flavor Discourse uses. I experience some unexpected behavior with non-alphanumeric characters which is awkward especially because of the common letter ä in the Finnish alphabet. I got the regex into pretty good shape by basic knowledge about regexes and the method of trial and error, but for an even better result, I would need documentation or something.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [April 24, 2017, 10:31pm UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/2 "2017-04-24T22:31:44Z")

</div>

You can read about it in the [source code](https://github.com/discourse/discourse/blob/0f2de4863b9b35289f0e37ff8ae0d52a5bc4bafc/app/assets/javascripts/pretty-text/censored-words.js.es6).

---

<div class="post-metadata">

### Author: ![elijah](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/elijah/32/104055_2.png) [@elijah](https://meta.discourse.org/u/elijah)
#### Post date: [April 24, 2017, 10:38pm UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/3 "2017-04-24T22:38:06Z")

</div>

Reading that, I don’t see much about them except to see that they are _Javascript_ regular expressions. (I would have assumed Ruby without that link.) So a Javascript reference would be in order.

> **[RegExp - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp)**
>
> The RegExp object is used for matching text with a pattern.

Which has internal links to specifications, if you want to go deeper.

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [April 25, 2017, 12:29am UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/4 "2017-04-25T00:29:24Z")

</div>

> [@rizka](#):
>
> which regex flavor Discourse uses.

AFAIK, Ruby and Postgres support POSiX

> **[Class: Regexp (Ruby 2.2.0)](https://ruby-doc.org/core-2.2.0/Regexp.html)**
>
> Class : Regexp - Ruby 2.2.0

> **[9.7. Pattern Matching](https://www.postgresql.org/docs/9.3/functions-matching.html)**
>
> 9.7. Pattern Matching # 9.7.1. LIKE 9.7.2. SIMILAR TO Regular Expressions 9.7.3. POSIX Regular Expressions There are three separate approaches to …

---

<div class="post-metadata">

### Author: ![rizka](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rizka/32/79717_2.png) [@rizka](https://meta.discourse.org/u/rizka)
#### Post date: [April 25, 2017, 8:26am UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/5 "2017-04-25T08:26:31Z")

</div>

Cool, thank you for your replies all. I’ll look into them and return if I still can’t figure it out.

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [May 28, 2019, 8:40pm UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/6 "2019-05-28T20:40:31Z")

</div>



---

<div class="post-metadata">

### Author: ![justin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/justin/32/157614_2.png) [@justin](https://meta.discourse.org/u/justin)
#### Post date: [May 29, 2019, 6:04pm UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/9 "2019-05-29T18:04:46Z")

</div>

### Discourse Regexes (Watched Words)

> 📣 To use regular expressions (regex) in watched words you must first turn on the `watched words regular expressions` site setting.

Discourse by default matches all uppercase and lowercase forms of a word entered as a regular expression. That is,

> `thread`

This will match `thread`, `THREAD`, and `thReAd`.

> `(t|7)hr(3|e)(4|a)d`

This will match all of the cases above, plus `thr3ad`, `7hread`, and `thr34d`.

> `threads?\S+`

This will match `thread` and `threads` but not `threaded` or `threading`.

However, 🛑 there’s a glaring error in _ALL_ the above examples! The words `threadlike` and `unthreading` are matched (`un▪️▪️▪️▪️▪️ing`), even though they’re not referring to `thread`. How do we fix that?

We’d have to amend our regex to handle word boundaries.

> `\bthreads?\b`

This looks for boundaries around the word so that `unthreading` or `threadlike` aren’t caught by the filter, but `thread` and `threads` still are.

For handling Unicode characters

> `gr(ü|ue)(ß|ss)e`

This matches all commonly spelled forms of the word grüße — including `gruesse` and `GRÜSSE`

Say we want to block the word `Über`, but not `Übersicht`. Using word boundaries like `\b(ü|ue)ber\b` doesn’t work because some of the JavaScript regex word flags don’t handle Unicode characters.

Instead we have to make our own boundaries.

> `(?:^|\s)(ü|ue)ber\b`

This will now appropriately match `Über` and `ueber`, but not `Übersicht` or `uebersicht`.

### A final warning

Regex is extremely powerful and thus dangerous. An incorrectly written regex statement can cause issues for your users. Test your regex statements on non-production instances before going live.

---

<div class="post-metadata">

### Author: ![supermathie](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/supermathie/32/507518_2.png) [@supermathie](https://meta.discourse.org/u/supermathie)
#### Post date: [May 30, 2019, 1:43am UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/13 "2019-05-30T01:43:11Z")

</div>

> [@justin](#):
>
> Test your regex statements on non-production instances before going live.

If you want to get more serious (or silly) about this kind of thing, you can introduce formal test cases. For example, I’ve put @justin’s über-excellent example onto [regex101.com](http://regex101.com): [https://regex101.com/r/4ano0r/1/tests](https://regex101.com/r/4ano0r/1/tests)

 ![image](https://global.discourse-cdn.com/meta/original/3X/2/0/202c625e3a4891c0e4628d37af2c2cd836638f3a.png)

If you do so, ensure you switch the regex flavour to ECMAScript:

> ![image](https://global.discourse-cdn.com/meta/original/3X/6/1/613239a4293a5e44a32e879095f5553accb8d41b.png)

hey, they spelled _flavour_ wrong 😠

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [June 29, 2019, 1:43am UTC](https://meta.discourse.org/t/how-to-use-discourse-regexes-with-watched-words/61522/14 "2019-06-29T01:43:15Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
