# Operators

Nushell supports the following operators for common math, logic, and string operations:

OperatorDescription
`+`add
`-`subtract
`*`multiply
`/`divide
`//`floor division
`mod`modulo
`**`exponentiation (power)
`==`equal
`!=`not equal
`<`less than
`<=`less than or equal
`>`greater than
`>=`greater than or equal
`=~`regex match / string contains another
`!~`inverse regex match / string does not contain another
`in`value in list
`not-in`value not in list
`not`logical not
`and`and two Boolean expressions (short-circuits)
`or`or two Boolean expressions (short-circuits)
`xor`exclusive or two boolean expressions
`bit-or`bitwise or
`bit-xor`bitwise xor
`bit-and`bitwise and
`bit-shl`bitwise shift left
`bit-shr`bitwise shift right
`starts-with`string starts with
`ends-with`string ends with
`++`append lists

Parentheses can be used for grouping to specify evaluation order or for calling commands and using the results in an expression.

## Order of Operations

To understand the precedence of operations, you can run the command: `help operators | sort-by precedence -r`.

Presented in descending order of precedence, the article details the operations as follows:

• Parentheses (`()`)
• Exponentiation/Power (`**`)
• Multiply (`*`), Divide (`/`), Integer/Floor Division (`//`), and Modulo (`mod`)
• Add (`+`) and Subtract (`-`)
• Bit shifting (`bit-shl`, `bit-shr`)
• Comparison operations (`==`, `!=`, `<`, `>`, `<=`, `>=`), membership tests (`in`, `not-in`, `starts-with`, `ends-with`), regex matching (`=~`, `!~`), and list appending (`++`)
• Bitwise and (`bit-and`)
• Bitwise xor (`bit-xor`)
• Bitwise or (`bit-or`)
• Logical and (`and`)
• Logical xor (`xor`)
• Logical or (`or`)
• Assignment operations
• Logical not (`not`)
``````> 3 * (1 + 2)
9
``````

## Types

Not all operations make sense for all data types. If you attempt to perform an operation on non-compatible data types, you will be met with an error message that should explain what went wrong:

``````> "spam" - 1

× Types mismatched for operation.
╭─[entry #49:1:1]
1 │ "spam" - 1
· ───┬── ┬ ┬
·    │   │ ╰── int
·    │   ╰── doesn't support these values.
·    ╰── string
╰────
help: Change string or int to be the right types and try again.
``````

The rules might sometimes feel a bit strict, but on the other hand there should be less unexpected side effects.

## Regular Expression / string-contains Operators

The `=~` and `!~` operators provide a convenient way to evaluate regular expressionsopen in new window. You don't need to know regular expressions to use them - they're also an easy way to check whether 1 string contains another.

• `string =~ pattern` returns true if `string` contains a match for `pattern`, and false otherwise.
• `string !~ pattern` returns false if `string` contains a match for `pattern`, and true otherwise.

For example:

``````foobarbaz =~ bar # returns true
foobarbaz !~ bar # returns false
ls | where name =~ ^nu # returns all files whose names start with "nu"
``````

Both operators use the Rust regex crate's `is_match()` functionopen in new window.

## Case Sensitivity

Operators are usually case-sensitive when operating on strings. There are a few ways to do case-insensitive work instead:

1. In the regular expression operators, specify the `(?i)` case-insensitive mode modifier:
``````"FOO" =~ "foo" # returns false
"FOO" =~ "(?i)foo" # returns true
``````
1. Use the `str contains` command's `--ignore-case` flag:
``````"FOO" | str contains --ignore-case "foo"
``````
1. Convert strings to lowercase with `str downcase` before comparing:
``````("FOO" | str downcase) == ("Foo" | str downcase)
``````

Nushell has a spread operator (`...`) for unpacking lists and records. You may be familiar with it if you've used JavaScript before. Some languages use `*` for their spread/splat operator. It can expand lists or records in places where multiple values or key-value pairs are expected.

There are three places you can use the spread operator:

### In list literals

Suppose you have multiple lists you want to concatenate together, but you also want to intersperse some individual values. This can be done with `append` and `prepend`, but the spread operator can let you do it more easily.

``````> let dogs = [Spot, Teddy, Tommy]
> let cats = ["Mr. Humphrey Montgomery", Kitten]
> [
...\$dogs
Polly
...(\$cats | each { |it| \$"(\$it) \(cat\)" })
...[Porky Bessie]
...Nemo
]
╭───┬───────────────────────────────╮
│ 0 │ Spot                          │
│ 1 │ Teddy                         │
│ 2 │ Tommy                         │
│ 3 │ Polly                         │
│ 4 │ Mr. Humphrey Montgomery (cat) │
│ 5 │ Kitten (cat)                  │
│ 6 │ Porky                         │
│ 7 │ Bessie                        │
│ 8 │ ...Nemo                       │
╰───┴───────────────────────────────╯
``````

The below code is an equivalent version using `append`:

``````> \$dogs |
append Polly |
append (\$cats | each { |it| \$"(\$it) \(cat\)" }) |
append [Porky Bessie] |
append ...Nemo
``````

Note that each call to `append` results in the creation of a new list, meaning that in this second example, 3 unnecessary intermediate lists are created. This is not the case with the spread operator, so there may be (very minor) performance benefits to using `...` if you're joining lots of large lists together, over and over.

You may have noticed that the last item of the resulting list above is `"...Nemo"`. This is because inside list literals, it can only be used to spread lists, not strings. As such, inside list literals, it can only be used before variables (`...\$foo`), subexpressions (`...(foo)`), and list literals (`...[foo]`).

The `...` also won't be recognized as the spread operator if there's any whitespace between it and the next expression:

``````> [ ... [] ]
╭───┬────────────────╮
│ 0 │ ...            │
│ 1 │ [list 0 items] │
╰───┴────────────────╯
``````

This is mainly so that `...` won't be confused for the spread operator in commands such as `mv ... \$dir`.

### In record literals

Let's say you have a record with some configuration information and you want to add more fields to this record:

``````> let config = { path: /tmp, limit: 5 }
``````

You can make a new record with all the fields of `\$config` and some new additions using the spread operator. You can use the spread multiple records inside a single record literal.

``````> {
...\$config,
users: [alice bob],
...{ url: example.com },
...(sys mem)
}
╭────────────┬───────────────╮
│ path       │ /tmp          │
│ limit      │ 5             │
│            │ ╭───┬───────╮ │
│ users      │ │ 0 │ alice │ │
│            │ │ 1 │ bob   │ │
│            │ ╰───┴───────╯ │
│ url        │ example.com   │
│ total      │ 8.3 GB        │
│ free       │ 2.6 GB        │
│ used       │ 5.7 GB        │
│ available  │ 2.6 GB        │
│ swap total │ 2.1 GB        │
│ swap free  │ 18.0 MB       │
│ swap used  │ 2.1 GB        │
╰────────────┴───────────────╯
``````

Similarly to lists, inside record literals, the spread operator can only be used before variables (`...\$foo`), subexpressions (`...(foo)`), and record literals (`...{foo:bar}`). Here too, there needs to be no whitespace between the `...` and the next expression for it to be recognized as the spread operator.

### In command calls

You can also spread arguments to a command, provided that it either has a rest parameter or is an external command.

Here is an example custom command that has a rest parameter:

``````> def foo [ --flag req opt? ...args ] { [\$flag, \$req, \$opt, \$args] | to nuon }
``````

It has one flag (`--flag`), one required positional parameter (`req`), one optional positional parameter (`opt?`), and rest parameter (`args`).

If you have a list of arguments to pass to `args`, you can spread it the same way you'd spread a list inside a list literal. The same rules apply: the spread operator is only recognized before variables, subexpressions, and list literals, and no whitespace is allowed in between.

``````> foo "bar" "baz" ...[1 2 3] # With ..., the numbers are treated as separate arguments
[false, bar, baz, [1, 2, 3]]
> foo "bar" "baz" [1 2 3] # Without ..., [1 2 3] is treated as a single argument
[false, bar, baz, [[1, 2, 3]]]
``````

A more useful way to use the spread operator is if you have another command with a rest parameter and you want it to forward its arguments to `foo`:

``````> def bar [ ...args ] { foo --flag "bar" "baz" ...\$args }
> bar 1 2 3
[true, bar, baz, [1, 2, 3]]
``````

You can spread multiple lists in a single call, and also intersperse individual arguments:

``````> foo "bar" "baz" 1 ...[2 3] 4 5 ...(6..9 | take 2) last
[false, bar, baz, [1, 2, 3, 4, 5, 6, 7, last]]
``````

Flags/named arguments can go after a spread argument, just like they can go after regular rest arguments:

``````> foo "bar" "baz" 1 ...[2 3] --flag 4
[true, bar, baz, [1, 2, 3, 4]]
``````

If a spread argument comes before an optional positional parameter, that optional parameter is treated as being omitted:

``````> foo "bar" ...[1 2] "not opt" # The null means no argument was given for opt
[false, bar, null, [1, 2, "not opt"]]
``````
Contributors: Justin Ma, JT, Hofer-Julian, Maxim Uvarov, Reilly Wood, 1submarine, Anselm Schüler, Darren Schroeder, Ian Manske, JT, Jakub Žádník, R. Mark Volkmann, Stefan Holderbach, Wenbo, Yash Thakur