# lookaround

[JS](/web/js.md) ⟩ [value](/web/js/val.md) ⟩ [object](/web/js/val/obj.md) ⟩ [regex](/web/js/val/builtin/regex.md) ⟩ [pattern](/web/js/val/builtin/regex/pattern.md) ⟩ lookaround

{% hint style="success" %}

```javascript
(?=...)	    // Positive lookahead (match the position before the specified regex)
(?!...)	    // Negative lookahead (don’t match, as above)
(?<=...)    // Positive lookbehind (match the position after the specified regex)
(?<!...)    // Negative lookbehind (don't match, as above)    
```

{% endhint %}

{% tabs %}
{% tab title="📗 參考" %}

* [ ] JS.info ⟩ [Lookahead & lookbehind](https://javascript.info/regexp-lookahead-lookbehind)
* [ ] [Regular Expression Quick Reference](http://regexrenamer.sourceforge.net/help/regex_quickref.html)
  {% endtab %}

{% tab title="📘 手冊" %}
\*
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="JS" %}

```javascript
const {log} = console;

/*
  Symbols
  -------
  • ? : lookaround
  • = : positive
  • ! : negative (NOT)
  • < : lookbehind

  lookahead: X(?=Y)
  ------------------
  match X (followed "immediately" by Y): 
  match X ("lookahead" for Y)
  
  lookahead: X(?=Y)(?=Z)
  -----------------------
  match X (followed "immediately" by Y & Z)
  match X ("lookahead" for Y & Z)
  
  negative lookahead: X(?!Y)
  ---------------------------
  match X (NOT followed "immediately" by Y)
  match X ("negative lookahead" for Y)
  
  Lookbehind: (?<=Y)X
  --------------------
  match X ("immediately" following Y)

  Negative Lookbehind: (?<!Y)X
  -----------------------------
  match X (NOT "immediately" following Y)
*/

//          ↱ space        ╭╮
let str = "1 turkey costs $30€";
//          ╰──── .*30 ─────╯

[
  // lookahead
  // ----------
  //         ╭X╮   Y
  str.match(/\d+(?=€)/),            // ["30"]
  
  //         ╭X╮   ╭╮    ╭──╮
  str.match(/\d+(?=\s)(?=.*30)/),   // ["1"]
  str.match(/\d+(?=.*30)(?=\s)/),   // ["1"]
  
  str.match(/\d+(?=30)(?=\s)/),     // ⭐️ null 
  // (no digits are followed "immediately" by "30")
  
  // negative lookahead
  // ------------------
  str.match(/\d+\b(?!€)/g),         // ["1"]
  //         ╰─╯╰╯   ↑
  
  // lookbehind: 
  // ----------
  //  escaped $ ➞╭╮ ╭─╮
  str.match(/(?<=\$)\d+/),          // ["30"]
  
].forEach(x => log(x))
```

{% endtab %}

{% tab title="💾 程式" %}

* codepen ⟩ [regex: lookaround](https://codepen.io/lochiwei/pen/eYEppJW?editors=0012)
* codewars ⟩ [Regex Password Validation](https://www.codewars.com/kata/52e1476c8147a7547a000811/train/javascript)
  {% endtab %}

{% tab title="📗 參考" %}

* [x] RegExr ⟩ [Password Validation](https://regexr.com/3bfsi)
  {% endtab %}

{% tab title="🗣 討論" %}

* [RegEx to make sure that the string contains at least one lower case char, upper case char, digit and symbol](https://stackoverflow.com/questions/1559751/regex-to-make-sure-that-the-string-contains-at-least-one-lower-case-char-upper)

```javascript
(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*\W)
```

{% endtab %}
{% endtabs %}

## examples

### Password Validation

```javascript
// Look ahead
// -----------
// (?=.*\d)       : at least one digit.
// (?=.*[a-z])    : at least one lower case.
// (?=.*[A-Z])    : at least one upper case.
// [0-9a-zA-Z]{6,}: at least 6 alphanumeric characters.
// /^...$/        : whole line
function validate(password) {
  return /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,}$/.test(password);
}
```

### words with (-) or (')

{% tabs %}
{% tab title="regex" %}

```javascript
// (?=[a-zA-Z'-]*[a-zA-Z]): at least one alphabet character
// 
/(?=[a-zA-Z'-]*[a-zA-Z])[a-zA-Z'-]+/g
```

{% endtab %}

{% tab title="💾 程式" %}

* RegEx ⟩ [words with (-) and (')](https://regexr.com/67k4i)
  {% endtab %}

{% tab title="🗣 討論" %}

* [Regex to match words with hyphens and/or apostrophes](https://stackoverflow.com/questions/31910955/regex-to-match-words-with-hyphens-and-or-apostrophes)
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/web/js/val/builtin/regex/pattern/lookaround.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
