|
| 1 | +--- |
| 2 | +title: indexof_regex |
| 3 | +description: 'This page explains how to use the indexof_regex function in APL.' |
| 4 | +--- |
| 5 | + |
| 6 | +Use the `indexof_regex` function to find the position of the first match of a regular expression in a string. The function is helpful when you want to locate a pattern within a larger text field and take action based on its position. For example, you can use `indexof_regex` to extract fields from semi-structured logs, validate string formats, or trigger alerts when specific patterns appear in log data. |
| 7 | + |
| 8 | +The function returns the zero-based index of the first match. If no match is found, it returns `-1`. Use `indexof_regex` when you need more flexibility than simple substring search (`indexof`), especially when working with dynamic or non-fixed patterns. |
| 9 | + |
| 10 | +<Note> |
| 11 | +All regex functions of APL use the [RE2 regex syntax](https://github.com/google/re2/wiki/Syntax). |
| 12 | +</Note> |
| 13 | + |
| 14 | +## For users of other query languages |
| 15 | + |
| 16 | +If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL. |
| 17 | + |
| 18 | +<AccordionGroup> |
| 19 | +<Accordion title="Splunk SPL users"> |
| 20 | + |
| 21 | +Use `match()` in Splunk SPL to perform regular expression matching. However, `match()` returns a Boolean, not the match position. APL’s `indexof_regex` is similar to combining `match()` with additional logic to extract position, which is not natively supported in SPL. |
| 22 | + |
| 23 | +<CodeGroup> |
| 24 | +```sql Splunk example |
| 25 | +... | eval match_index=if(match(field, "pattern"), 0, -1) |
| 26 | +```` |
| 27 | + |
| 28 | +```kusto APL equivalent |
| 29 | +['dataset'] |
| 30 | +| extend match_index = indexof_regex(field, 'pattern') |
| 31 | +``` |
| 32 | + |
| 33 | +</CodeGroup> |
| 34 | + |
| 35 | +</Accordion> |
| 36 | +<Accordion title="ANSI SQL users"> |
| 37 | + |
| 38 | +ANSI SQL does not have a built-in function to return the index of a regex match. You typically use `REGEXP_LIKE` for Boolean evaluation. `indexof_regex` provides a more direct and powerful way to find the exact match position in APL. |
| 39 | + |
| 40 | +<CodeGroup> |
| 41 | +```sql SQL example |
| 42 | +SELECT CASE WHEN REGEXP_LIKE(field, 'pattern') THEN 0 ELSE -1 END FROM table; |
| 43 | +``` |
| 44 | + |
| 45 | +```kusto APL equivalent |
| 46 | +['dataset'] |
| 47 | +| extend match_index = indexof_regex(field, 'pattern') |
| 48 | +``` |
| 49 | + |
| 50 | +</CodeGroup> |
| 51 | + |
| 52 | +</Accordion> |
| 53 | +</AccordionGroup> |
| 54 | + |
| 55 | +## Usage |
| 56 | + |
| 57 | +### Syntax |
| 58 | + |
| 59 | +```kusto |
| 60 | +indexof_regex(string, match [, start [, occurrence [, length]]]) |
| 61 | +``` |
| 62 | + |
| 63 | +### Parameters |
| 64 | + |
| 65 | +| Name | Type | Required | Description | |
| 66 | +| ---------- | ------ | -------- | --- | |
| 67 | +| string | string | Yes | The input text to inspect. | |
| 68 | +| match | string | Yes | The regular expression pattern to search for. | |
| 69 | +| start | int | | The index in the string where to begin the search. If negative, the function starts that many characters from the end. | |
| 70 | +| occurrence | int | | Which instance of the pattern to match. Defaults to `1` if not specified. | |
| 71 | +| length | int | | The number of characters to search through. Use `-1` to search to the end of the string. | |
| 72 | + |
| 73 | +### Returns |
| 74 | + |
| 75 | +The function returns the position (starting at zero) where the pattern first matches within the string. If the pattern is not found, the result is `-1`. |
| 76 | + |
| 77 | +The function returns `null` in the following cases: |
| 78 | + |
| 79 | +- The `start` value is negative. |
| 80 | +- The `occurrence` value is less than 1. |
| 81 | +- The `length` is set to a value below `-1`. |
| 82 | + |
| 83 | +## Use case examples |
| 84 | + |
| 85 | +<Tabs> |
| 86 | +<Tab title="Log analysis"> |
| 87 | + |
| 88 | +Use `indexof_regex` to detect whether the URI in a log entry contains an encoded user ID by checking for patterns like `user-[0-9]+`. |
| 89 | + |
| 90 | +**Query** |
| 91 | + |
| 92 | +```kusto |
| 93 | +['sample-http-logs'] |
| 94 | +| extend user_id_pos = indexof_regex(uri, 'user-[0-9]+') |
| 95 | +| where user_id_pos != -1 |
| 96 | +| project _time, id, uri, user_id_pos |
| 97 | +``` |
| 98 | + |
| 99 | +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20user_id_pos%20%3D%20indexof_regex(uri%2C%20'user-%5B0-9%5D%2B')%20%7C%20where%20user_id_pos%20!%3D%20-1%20%7C%20project%20_time%2C%20id%2C%20uri%2C%20user_id_pos%22%7D) |
| 100 | + |
| 101 | +**Output** |
| 102 | + |
| 103 | +| _time | id | uri | user_id_pos | |
| 104 | +| -------------------- | ------ | ------------------------ | ------------- | |
| 105 | +| 2025-06-10T12:34:56Z | user42 | /api/user-12345/settings | 5 | |
| 106 | +| 2025-06-10T12:35:07Z | user91 | /v2/user-6789/dashboard | 4 | |
| 107 | + |
| 108 | +The query finds log entries where the URI contains a user ID pattern and shows the position of the match in the URI string. |
| 109 | + |
| 110 | +</Tab> |
| 111 | +<Tab title="OpenTelemetry traces"> |
| 112 | + |
| 113 | +Use `indexof_regex` to detect trace IDs that include a specific structure, such as four groups of hex digits. |
| 114 | + |
| 115 | +**Query** |
| 116 | + |
| 117 | +```kusto |
| 118 | +['otel-demo-traces'] |
| 119 | +| extend match_index = indexof_regex(trace_id, '^[0-9a-f]{8}-[0-9a-f]{4}') |
| 120 | +| where match_index == 0 |
| 121 | +| project _time, trace_id, match_index |
| 122 | +``` |
| 123 | + |
| 124 | +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20extend%20match_index%20%3D%20indexof_regex(trace_id%2C%20'%5E%5B0-9a-f%5D%7B8%7D-%5B0-9a-f%5D%7B4%7D')%20%7C%20where%20match_index%20%3D%3D%200%20%7C%20project%20_time%2C%20trace_id%2C%20match_index%22%7D) |
| 125 | + |
| 126 | +**Output** |
| 127 | + |
| 128 | +| _time | trace_id | match_index | |
| 129 | +| -------------------- | ------------------------------------ | ------------ | |
| 130 | +| 2025-06-10T08:23:12Z | ab12cd34-1234-5678-9abc-def123456789 | 0 | |
| 131 | +| 2025-06-10T08:24:55Z | fe98ba76-4321-abcd-8765-fedcba987654 | 0 | |
| 132 | + |
| 133 | +This query finds spans where the trace ID begins with a specific regex pattern, helping validate span ID formatting. |
| 134 | + |
| 135 | +</Tab> |
| 136 | +<Tab title="Security logs"> |
| 137 | + |
| 138 | +Use `indexof_regex` to locate suspicious request patterns such as attempts to access system files (`/etc/passwd`). |
| 139 | + |
| 140 | +**Query** |
| 141 | + |
| 142 | +```kusto |
| 143 | +['sample-http-logs'] |
| 144 | +| extend passwd_index = indexof_regex(uri, '/etc/passwd') |
| 145 | +| where passwd_index != -1 |
| 146 | +| project _time, id, uri, passwd_index |
| 147 | +``` |
| 148 | + |
| 149 | +[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20extend%20passwd_index%20%3D%20indexof_regex(uri%2C%20'%2Fetc%2Fpasswd')%20%7C%20where%20passwd_index%20!%3D%20-1%20%7C%20project%20_time%2C%20id%2C%20uri%2C%20passwd_index%22%7D) |
| 150 | + |
| 151 | +**Output** |
| 152 | + |
| 153 | +| _time | id | uri | passwd_index | |
| 154 | +| -------------------- | ------ | ------------------------------ | ------------- | |
| 155 | +| 2025-06-10T10:15:45Z | user88 | /cgi-bin/view?path=/etc/passwd | 20 | |
| 156 | + |
| 157 | +This query detects HTTP requests attempting to access sensitive file paths, a common indicator of intrusion attempts. |
| 158 | + |
| 159 | +</Tab> |
| 160 | +</Tabs> |
0 commit comments