execline: the case command
Keywords: execline command case regex grep

execline
Software
skarnet.org

# The `case` program

`case` compares a value against a series of regular expressions, and executes into a program depending on the first expression the value matches.

## Interface

In an execlineb script:

         case [ -S | -s ] [ -E | -e ] [ -i ] [ -n | -N ] value
         {
           [ regex { prog... } ]
           [ regex { prog... } ]
           ...
         }
         progdefault...

- `case` reads an argument value and a sequence of directives in a block.
- Each directive is a regular expression followed by a block.
- `case` matches value against the regular expressions in the order they are given.
- As soon as value matches a regex, `case` executes into the prog... command line that immediately follows the matched regex.
- If value matches no regex, `case` eventually execs into progdefault..., or exits 0 if progdefault... is empty.

## Options

- `-s` : Shell matching. The regex words will not be interpreted as regular expressions, but as shell expressions to be interpreted via fnmatch(). The other options also change meanings, see the Shell matching section below.
- `-S` : Regular expression matching. This is the default. This section, and all of the sections below except the Shell matching one, assumes that it is the case.
- `-e` : Interpret the regex words as basic regular expressions.
- `-E` : Interpret the regex words as extended regular expressions. This is the default.
- `-i` : Perform case-insensitive matches.
- `-N` : Make the matching expression and subexpressions available to prog's environment. See the "Subexpression matching" section below.
- `-n` : Do not transmit the matching expression and subexpressions to prog... via the environment. This is the default.

## Subexpression matching

If the `-N` option has been given, and value matches a regex, then `case` will run prog with a modified environment:

- The `0` variable will contain the regex that value matched.
- The `#` variable will contain the number of subexpressions in regex.
- For every integer i between 1 and the number of subexpressions (included), the variable i contains the part of value that matched the ith subexpression in regex.

To retrieve that information into your command line in an execline script, you can use the elgetpositionals program.

### An example

Consider the following script; say it's named `match`.

    #!/bin/execlineb -S1
    emptyenv
    case -N -- $1
    {
      "([fo]+)bar(baz)" { /usr/bin/env }
    }

Running `match foooobarbaz` will print the following lines, corresponding to the output of the `/usr/bin/env` command:

    #=2
    0=([fo]+)bar(baz)
    1=foooo
    2=baz

## Shell matching

If the `-s` option has been given to `case`, then the regex words are not interpreted as regular expressions, but as shell patterns, as is performed by the shell's case conditional construct. This has the following consequences:

- Subexpression matching is always disabled.
- prog... is always executed with an unmodified environment.
- The options to the `case` command change meanings: instead of controlling how the regex regular expressions are interpreted by the regcomp() primitive, they now control how value is matched against the regex patterns (which are not regular expressions!) via the fnmatch() primitive. Namely:
  - `-e` : Treat a backslash as an ordinary character; do not allow character escaping in patterns. (This sets the `FNM_NOESCAPE` flag.)
  - `-E` : Allow backslash escaping in patterns. This is the default. (This clears the `FNM_NOESCAPE` flag.)
  - `-i` : Treat a period (`.`) as a special character for matching (set `FNM_PERIOD`). By default, the period is not a special character (`FNM_PERIOD` is cleared).
  - `-N` : Treat patterns as pathnames: make slashes character special. (This sets the `FNM_PATHNAME` flag.)
  - `-n` : Do not treat patterns as pathnames (clear the `FNM_PATHNAME` flag). This is the default.

## Notes

- value must match regex as a full word. If only a substring of value matches regex, it is not considered a match.
- If value matches no regex, progdefault... is always executed with an unmodified environment, whether subexpression matching has been requested or not.