# `TextFSM`
[🔗](https://github.com/amitbashan/textfsm/blob/main/lib/textfsm.ex#L1)

TextFSM is a template-based state machine for parsing semi-structured text.

This is an Elixir implementation of the [TextFSM](https://github.com/google/textfsm) library written in Python.
TextFSM allows you to define a template that describes the structure of your text (e.g. CLI output from network devices)
and parse it into a structured table.

## Example

    template = """
    Value INTERFACE (\\S+)
    Value IP_ADDRESS (\\d+\.\\d+\.\\d+\.\\d+|unassigned)
    Value STATUS (up|down|administratively down)
    Value PROTOCOL (up|down)

    Start
      ^${INTERFACE}\\s+${IP_ADDRESS}\\s+\\w+\\s+\\w+\\s+${STATUS}\\s+${PROTOCOL} -> Record
    """

    text = """
    Interface              IP-Address      OK? Method Status                Protocol
    GigabitEthernet0/0     192.168.1.1     YES NVRAM  up                    up
    GigabitEthernet0/1     unassigned      YES NVRAM  administratively down down
    GigabitEthernet0/2     10.0.0.5        YES manual up                    up
    Loopback0              127.0.0.1       YES unset  up                    up
    """

    {:ok, result} = TextFSM.parse(template, text)

  Result:

    %{
      "INTERFACE" => ["GigabitEthernet0/0", "GigabitEthernet0/1",
      "GigabitEthernet0/2", "Loopback0"],
      "IP_ADDRESS" => ["192.168.1.1", "unassigned", "10.0.0.5", "127.0.0.1"],
      "PROTOCOL" => ["up", "down", "up", "up"],
      "STATUS" => ["up", "administratively down", "up", "up"]
    }

# `byte_offset`

```elixir
@type byte_offset() :: non_neg_integer()
```

# `context`

```elixir
@type context() :: map()
```

# `line`

```elixir
@type line() :: {pos_integer(), byte_offset()}
```

# `parse_error`

```elixir
@type parse_error() :: {:error, reason(), rest(), context(), line(), byte_offset()}
```

# `reason`

```elixir
@type reason() :: String.t()
```

# `rest`

```elixir
@type rest() :: binary()
```

# `table`

```elixir
@type table() :: %{required(value_name()) =&gt; [value()]}
```

# `validation_message`

```elixir
@type validation_message() :: {:error, String.t()} | {:warning, String.t()}
```

# `value`

```elixir
@type value() :: nil | String.t() | [String.t()]
```

# `value_name`

```elixir
@type value_name() :: String.t()
```

# `parse`

```elixir
@spec parse(binary(), binary(), String.t()) ::
  {:ok, table()} | parse_error() | [validation_message()]
```

Parses text using the provided TextFSM template.

## Parameters

* `template` - A string containing the TextFSM template.
* `text` - The input text to be parsed.
* `modifiers` - Regex modifiers, see `Regex` module.

## Returns

* `{:ok, table}` - A column-oriented table represented as a map from value names to columns.
* `{:error, ...}` - If parsing of the TextFSM template fails. See `parse_template/1` for more details.

# `parse_template`

```elixir
@spec parse_template(binary(), String.t()) ::
  {:ok, TextFSM.Template.t()} | parse_error() | [validation_message()]
```

Parses and compiles a TextFSM template string.

This function takes the raw template string, parses it into its internal representation,
validates the structure, and compiles the regular expressions for execution.

## Parameters

* `template` - A string containing the TextFSM template definition.
* `modifiers` - Regex modifiers, see `Regex` module.

## Returns

* `{:ok, template}`
* `{:error, reason, rest, context, line, byte_offset}` - If the template syntax is invalid.
* `{:error, [messages]}` - If the template fails validation.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
