Skip to content

Commit ab3f8f5

Browse files
authored
[DOCS] EQL: Add case-insensitive ~ operator (#68217)
Documents the case-insensitive `~` operator for `in` and string functions. Relates to #67869 and #68176
1 parent 28ac8c9 commit ab3f8f5

File tree

2 files changed

+66
-18
lines changed

2 files changed

+66
-18
lines changed

docs/reference/eql/functions.asciidoc

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
<titleabbrev>Function reference</titleabbrev>
77
++++
88

9-
{es} supports the following <<eql-functions,EQL functions>>. Most EQL functions
10-
are case-sensitive by default.
9+
{es} supports the following <<eql-functions,EQL functions>>.
1110

1211
[discrete]
1312
[[eql-fn-add]]
@@ -61,27 +60,31 @@ If using a field as the argument, this parameter supports only
6160
=== `between`
6261

6362
Extracts a substring that's between a provided `left` and `right` text in a
64-
source string. Matching is case-sensitive.
63+
source string. Matching is case-sensitive by default.
6564

6665
*Example*
6766
[source,eql]
6867
----
6968
// file.path = "C:\\Windows\\System32\\cmd.exe"
70-
between(file.path, "system32\\\\", ".exe") // returns "cmd"
69+
between(file.path, "System32\\\\", ".exe") // returns "cmd"
70+
between(file.path, "system32\\\\", ".exe") // returns ""
7171
between(file.path, "workspace\\\\", ".exe") // returns ""
7272
73+
// Make matching case-insensitive
74+
between~(file.path, "system32\\\\", ".exe") // returns "cmd"
75+
7376
// Greedy matching defaults to false.
7477
between(file.path, "\\\\", "\\\\", false) // returns "Windows"
7578
7679
// Sets greedy matching to true
7780
between(file.path, "\\\\", "\\\\", true) // returns "Windows\\System32"
7881
7982
// empty source string
80-
between("", "system32\\\\", ".exe") // returns ""
83+
between("", "System32\\\\", ".exe") // returns ""
8184
between("", "", "") // returns ""
8285
8386
// null handling
84-
between(null, "system32\\\\", ".exe") // returns null
87+
between(null, "System32\\\\", ".exe") // returns null
8588
----
8689

8790
*Syntax*
@@ -340,15 +343,19 @@ If using a field as the argument, this parameter supports only
340343
=== `endsWith`
341344

342345
Returns `true` if a source string ends with a provided substring. Matching is
343-
case-sensitive.
346+
case-sensitive by default.
344347

345348
*Example*
346349
[source,eql]
347350
----
348351
endsWith("regsvr32.exe", ".exe") // returns true
352+
endsWith("regsvr32.exe", ".EXE") // returns false
349353
endsWith("regsvr32.exe", ".dll") // returns false
350354
endsWith("", "") // returns true
351355
356+
// Make matching case-insensitive
357+
endsWith~("regsvr32.exe", ".EXE") // returns true
358+
352359
// file.name = "regsvr32.exe"
353360
endsWith(file.name, ".exe") // returns true
354361
endsWith(file.name, ".dll") // returns false
@@ -405,7 +412,7 @@ field data types:
405412
=== `indexOf`
406413

407414
Returns the first position of a provided substring in a source string. Matching
408-
is case-sensitive.
415+
is case-sensitive by default.
409416

410417
If an optional start position is provided, this function returns the first
411418
occurrence of the substring at or after the start position.
@@ -414,11 +421,16 @@ occurrence of the substring at or after the start position.
414421
[source,eql]
415422
----
416423
// url.domain = "subdomain.example.com"
424+
indexOf(url.domain, "d") // returns 3
425+
indexOf(url.domain, "D") // returns null
417426
indexOf(url.domain, ".") // returns 9
418427
indexOf(url.domain, ".", 9) // returns 9
419428
indexOf(url.domain, ".", 10) // returns 17
420429
indexOf(url.domain, ".", -6) // returns 9
421430
431+
// Make matching case-insensitive
432+
indexOf~(url.domain, "D") // returns 4
433+
422434
// empty strings
423435
indexOf("", "") // returns 0
424436
indexOf(url.domain, "") // returns 0
@@ -748,15 +760,19 @@ Fields are not supported as arguments.
748760
=== `startsWith`
749761

750762
Returns `true` if a source string begins with a provided substring. Matching is
751-
case-sensitive.
763+
case-sensitive by default.
752764

753765
*Example*
754766
[source,eql]
755767
----
756768
startsWith("regsvr32.exe", "regsvr32") // returns true
769+
startsWith("regsvr32.exe", "Regsvr32") // returns false
757770
startsWith("regsvr32.exe", "explorer") // returns false
758771
startsWith("", "") // returns true
759772
773+
// Make matching case-insensitive
774+
startsWith~("regsvr32.exe", "Regsvr32") // returns true
775+
760776
// process.name = "regsvr32.exe"
761777
startsWith(process.name, "regsvr32") // returns true
762778
startsWith(process.name, "explorer") // returns false
@@ -848,16 +864,20 @@ If using a field as the argument, this parameter does not support the
848864
=== `stringContains`
849865

850866
Returns `true` if a source string contains a provided substring. Matching is
851-
case-sensitive.
867+
case-sensitive by default.
852868

853869
*Example*
854870
[source,eql]
855871
----
856872
// process.command_line = "start regsvr32.exe"
857873
stringContains(process.command_line, "regsvr32") // returns true
874+
stringContains(process.command_line, "Regsvr32") // returns false
858875
stringContains(process.command_line, "start ") // returns true
859876
stringContains(process.command_line, "explorer") // returns false
860877
878+
// Make matching case-insensitive
879+
stringContains~(process.command_line, "Regsvr32") // returns false
880+
861881
// process.name = "regsvr32.exe"
862882
stringContains(command_line, process.name) // returns true
863883
@@ -1008,18 +1028,22 @@ If using a field as the argument, this parameter supports only
10081028
=== `wildcard`
10091029

10101030
Returns `true` if a source string matches one or more provided wildcard
1011-
expressions. Matching is case-sensitive.
1031+
expressions. Matching is case-sensitive by default.
10121032

10131033
*Example*
10141034
[source,eql]
10151035
----
10161036
// The * wildcard matches zero or more characters.
10171037
// process.name = "regsvr32.exe"
10181038
wildcard(process.name, "*regsvr32*") // returns true
1039+
wildcard(process.name, "*Regsvr32*") // returns false
10191040
wildcard(process.name, "*regsvr32*", "*explorer*") // returns true
10201041
wildcard(process.name, "*explorer*") // returns false
10211042
wildcard(process.name, "*explorer*", "*scrobj*") // returns false
10221043
1044+
// Make matching case-insensitive
1045+
wildcard~(process.name, "*Regsvr32*") // returns true
1046+
10231047
// The ? wildcard matches exactly one character.
10241048
// process.name = "regsvr32.exe"
10251049
wildcard(process.name, "regsvr32.e?e") // returns true

docs/reference/eql/syntax.asciidoc

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,18 +220,28 @@ Returns `true` if the condition to the right is `false`.
220220
[source,eql]
221221
----
222222
user.name in ("Administrator", "SYSTEM", "NETWORK SERVICE")
223+
user.name in~ ("administrator", "system", "network service")
223224
user.name not in ("Administrator", "SYSTEM", "NETWORK SERVICE")
225+
user.name not in~ ("administrator", "system", "network service")
224226
user.name : ("administrator", "system", "network service")
225227
----
226228

227229
`in` (case-sensitive)::
228230
Returns `true` if the value is contained in the provided list. For strings,
229231
matching is case-sensitive.
230232

233+
`in~` (case-insensitive)::
234+
Returns `true` if the value is contained in the provided list. For strings,
235+
matching is case-insensitive.
236+
231237
`not in` (case-sensitive)::
232238
Returns `true` if the value is not contained in the provided list. For strings,
233239
matching is case-sensitive.
234240

241+
`not in~` (case-insensitive)::
242+
Returns `true` if the value is not contained in the provided list. For strings,
243+
matching is case-insensitive.
244+
235245
`:` (case-insensitive)::
236246
Returns `true` if the value is contained in the provided list. Can only be used
237247
to compare strings.
@@ -627,12 +637,25 @@ until [ process where event.type == "stop" ]
627637
=== Functions
628638

629639
You can use EQL functions to convert data types, perform math, manipulate
630-
strings, and more. Most functions are case-sensitive by default.
640+
strings, and more. For a list of supported functions, see <<eql-function-ref>>.
631641

632-
For a list of supported functions, see <<eql-function-ref>>.
642+
[discrete]
643+
[[eql-case-insensitive-functions]]
644+
=== Case-insensitive functions
645+
646+
Most EQL functions are case-sensitive by default. To make a function
647+
case-insensitive, use the `~` operator after the function name:
648+
649+
[source,eql]
650+
----
651+
stringContains(process.name,".exe") // Matches ".exe" but not ".EXE" or ".Exe"
652+
stringContains~(process.name,".exe") // Matches ".exe", ".EXE", or ".Exe"
653+
----
654+
655+
[discrete]
656+
[[eql-how-functions-impact-search-performance]]
657+
=== How functions impact search performance
633658

634-
[TIP]
635-
====
636659
Using functions in EQL queries can result in slower search speeds. If you
637660
often use functions to transform indexed data, you can speed up search by making
638661
these changes during indexing instead. However, that often means slower index
@@ -672,7 +695,6 @@ file where file.extension in ("exe", "dll")
672695

673696
We recommend testing and benchmarking any indexing changes before deploying them
674697
in production. See <<tune-for-indexing-speed>> and <<tune-for-search-speed>>.
675-
====
676698

677699
[discrete]
678700
[[eql-pipes]]
@@ -741,8 +763,10 @@ sub-fields of a `nested` field. However, data streams and indices containing
741763
{es} EQL differs from the {eql-ref}/index.html[Elastic Endgame EQL syntax] as
742764
follows:
743765

744-
* Most operators and functions in {es} EQL are case-sensitive. For
745-
case-insensitive equality comparisons, use the `:` operator.
766+
* Most operators and functions in {es} EQL are case-sensitive by default. For
767+
case-insensitive equality comparisons, use the `:` operator. To make a function
768+
case-insensitive, use the `~` operator after the function name. See
769+
<<eql-case-insensitive-functions>>.
746770

747771
* Comparisons using the `==` and `!=` operators do not expand wildcard
748772
characters. For example, `process_name == "cmd*.exe"` interprets `*` as a

0 commit comments

Comments
 (0)