Nushell
Get Nu!
Getting Started
  • The Nushell Book
  • Command Reference
  • Cookbook
  • Language Reference Guide
  • Contributing Guide
Blog
  • English
  • 中文
  • Deutsch
  • Français
  • Español
  • 日本語
  • Português do Brasil
  • Русский язык
  • 한국어
GitHub
Get Nu!
Getting Started
  • The Nushell Book
  • Command Reference
  • Cookbook
  • Language Reference Guide
  • Contributing Guide
Blog
  • English
  • 中文
  • Deutsch
  • Français
  • Español
  • 日本語
  • Português do Brasil
  • Русский язык
  • 한국어
GitHub
  • Language Reference Guide
    • Readme
    • Types in the Nu Language
      • Basic Types
        • Any
        • Boolean
        • Integer
        • Float
        • Filesize
        • Duration
        • Datetime
        • Range
        • String
        • Record
        • List
        • Table
        • Closure
        • Nothing
        • Binary
        • Glob
        • Cell-Path
      • Other Data Types

        • Types used only in command signatures
          • Path
        • Types which are not declarable
          • Error
          • CustomValue
          • Block
      • Type signatures
      • Commands that interact with types
    • Operators
    • Flow control
      • if/else
      • loop
      • while
      • match
      • try/catch
      • break
      • return
      • continue
    • Filters
      • each and par-each
      • Filters to select subsets of data
      • where and filter
      • Understanding the difference between get and select
    • Custom Commands
    • Declarations
    • Variable Scope
    • Strings and Text Formatting
    • Helpers and debugging commands
    • Pipelines
    • MIME Types for Nushell

match

match compares a value against a list of patterns, top to bottom, and evaluates the arm of the first pattern that matches. Like if, it is an expression: its result is the value of the chosen arm, so it can be assigned or piped.

match <value> {
  <pattern> => <expression>
  <pattern> if <condition> => <expression>
  ...
}

See also: match command help and Control Flow - match in the Book.

[1 5 12 -3] | each {|n|
  match $n {
    1 | 2 | 3 => 'small'
    4..10 => 'medium'
    $x if $x < 0 => 'negative'
    _ => 'large'
  }
}
# => ╭───┬──────────╮
# => │ 0 │ small    │
# => │ 1 │ medium   │
# => │ 2 │ large    │
# => │ 3 │ negative │
# => ╰───┴──────────╯

Patterns

PatternMatches
3, 'text', true, nullA value equal to the literal. A bare word such as foo is a string.
1..10, 5.., 1..<5A number inside the range
(40 + 2), ($some_const)The value of a parse-time constant expression
$nameAny value, and binds it to $name for the guard and the arm
_Any value (catch-all)
p1 | p2Either pattern
[$a, $b], []A list with exactly that many items
[$first, ..$rest], [.., $last], [$a, ..$m, $z]A list with at least the listed items; ..$rest binds the items .. stands for
{name: $n, type: file}A record that has at least these fields, with matching values
{$name}Shorthand for {name: $name}

List and record patterns can be nested, and a pattern can be followed by an if guard.

Language Notes

  1. Arms are separated by commas or newlines. An arm's result is a single expression. Use a block ({ ... }) for several statements:

    match 3 {
      1 => 'one'
      2 => 'two'
      $n => {
        let doubled = $n * 2
        $"($n) doubled is ($doubled)"
      }
    }
    # => 3 doubled is 6
  2. If no arm matches, match evaluates to nothing. End with _ => ... when every value must be handled.

    match 42 { 1 => 'one' } | describe
    # => nothing
  3. A $name pattern always binds a new variable. It never compares against an existing variable of the same name. The following matches 5, not 1:

    let expected = 1
    match 5 { $expected => $"matched ($expected)" }
    # => matched 5

    To compare against a runtime value, use a guard. To compare against a const, wrap it in parentheses:

    let expected = 1
    match 5 { $n if $n == $expected => 'expected', $n => $"unexpected ($n)" }
    # => unexpected 5
    const expected = 5
    match 5 { ($expected) => 'expected', _ => 'unexpected' }
    # => expected
  4. Values are compared by type as well as value, so the string "3" does not match the integer 3:

    match "3" { 3 => 'int', "3" => 'string' }
    # => string
  5. A list pattern without .. must have exactly as many items as the list:

    match [1 2 3] { [$a, $b] => 'two items', [$a, $b, $c] => 'three items' }
    # => three items
    match [1 2 3 4] { [$first, ..$rest] => {first: $first, rest: $rest} }
    # => ╭───────┬───────────╮
    # => │ first │ 1         │
    # => │       │ ╭───┬───╮ │
    # => │ rest  │ │ 0 │ 2 │ │
    # => │       │ │ 1 │ 3 │ │
    # => │       │ │ 2 │ 4 │ │
    # => │       │ ╰───┴───╯ │
    # => ╰───────┴───────────╯
  6. .. or ..$name can stand anywhere in a list pattern, not only at the end. The items before it match the start of the list, the items after it match the end, and ..$name binds whatever is left in between (an empty list when nothing is):

    match [1 2 3 4] { [$first, ..$middle, $last] => {first: $first, middle: $middle, last: $last} } | to nuon
    # => {first: 1, middle: [2, 3], last: 4}
    match [build test done] { [.., 'done'] => 'finished', _ => 'running' }
    # => finished

    A list pattern can hold only one ... A second one is a parse error, `..` can only be used once per list pattern. Each nested list pattern gets its own, so [[.., 2], ..] is allowed.

  7. A record pattern ignores extra fields, but every field it names must be present. Literal field values let you dispatch on a "tag" field:

    let events = [
      {type: click, x: 10, y: 20}
      {type: key, key: 'q'}
      {type: resize}
    ]
    $events | each {|e|
      match $e {
        {type: click, x: $x, y: $y} => $"click at ($x),($y)"
        {type: key, key: 'q'} => 'quit'
        {type: $t} => $"unhandled ($t)"
      }
    }
    # => ╭───┬──────────────────╮
    # => │ 0 │ click at 10,20   │
    # => │ 1 │ quit             │
    # => │ 2 │ unhandled resize │
    # => ╰───┴──────────────────╯
  8. A guard is checked only after its pattern matches, and it can use the variables the pattern bound. If the guard is false, matching continues with the next arm:

    match [1, 2] { [$a, $b] if $a > $b => 'descending', [$a, $b] => 'ascending' }
    # => ascending
  9. To match on pipeline input, pass $in as the value:

    {name: 'nu', version: 116} | match $in { {$name, $version} => $"($name) 0.($version)" }
    # => nu 0.116
Edit this page on GitHub
Contributors: NotTheDr01ds, Kieron Wilkinson, fdncred
Prev
while
Next
try/catch