(cli)=

# CLI Command

## Overview

ciscoconfparse2 adds a CLI command to search and diff configurations. The
syntax follows the API.

All CLI examples will use this configuration...

```none
!
router bgp 65111
 bgp router-id 192.0.2.200
 neighbor 192.0.2.1 remote-as 64000
 address-family ipv4 unicast
  default-information originate
  neighbor 192.0.2.1 activate
!
```

## Example 1: Find parent lines

If you want to find `router bgp 65111` (which has the child: `bgp router-id 192.0.2.200`) , use this CLI command...

```none
$ ccp parent -a 'router bgp,router-id' conf/path/or/file/glob.conf
```

The parent will be printed, and you should see:

```none
Syntax      : ios
Returing    : parent text
Output as   : raw_text
  parent: router bgp
  child : router-id
---------- file: conf/path/or/file/glob.conf ----------
router bgp 65111
```

That CLI command is the equivalent of running this
{func}`~ciscoconfparse2.CiscoConfParse.find_parent_objects` script:

```pycon
>>> from ciscoconfparse2 import CiscoConfParse
>>> parse = CiscoConfParse("conf/path/or/file/glob.conf")
>>> for obj in parse.find_parent_objects(["router bgp"]):
...     print(obj.text)
...
>>>
```

## Example 2: Find child lines

If you want to find `default-information originate`, use this CLI command

```none
$ ccp child -a 'router bgp,address-family,default-information' conf/path/or/file/glob.conf
```

The last child will be printed, and you should see:

```none
Syntax      : ios
Returing    : child text
Output as   : raw_text
  parent: router bgp
  child : address-family
  child : default-information
---------- file: conf/path/or/file/glob.conf ----------
default-information originate
```

That CLI command is the equivalent of running this
{func}`~ciscoconfparse2.CiscoConfParse.find_child_objects` script:

```pycon
>>> from ciscoconfparse2 import CiscoConfParse
>>> parse = CiscoConfParse("conf/path/or/file/glob.conf")
>>> for obj in parse.find_child_objects(
...     ["router bgp", "address-family", "default-information"]
... ):
...     print(obj.text)
...
>>>
```

## Example 3: Find branches as lists

A branch is just a list of all matching parent and child text lines. To find the branch
for 'default-information originate'...

```none
$ ccp branch -a 'router bgp,address-family,default-information' conf/path/or/file/glob.conf
```

The output will be:

```none
Syntax      : ios
Returing    : branch text
Output as   : raw_text
  parent: router bgp
  child : address-family
  child : default-information
---------- file: conf/path/or/file/glob.conf ----------
['router bgp 65111', ' address-family ipv4 unicast', '  default-information originate']
```

That CLI command is the equivalent of running this
{func}`~ciscoconfparse2.CiscoConfParse.find_object_branches` script:

```pycon
>>> from ciscoconfparse2 import CiscoConfParse
>>> parse = CiscoConfParse("conf/path/or/file/glob.conf")
>>> for branch in parse.find_object_branches(
...     ["router bgp", "address-family", "default-information"]
... ):
...     print([obj.text for obj in branch])
...
>>>
```

## Example 4: Find branches as the original configuration

You can also find branches as shown in the original configuration... just use:

```none
$ ccp branch -a 'router bgp' -o original conf/path/or/file/glob.conf
```

This will print...

```none
Syntax      : ios
Returing    : branch text
Output as   : original
  parent: router bgp
---------- file: conf/path/or/file/glob.conf ----------
router bgp 65111
 bgp router-id 192.0.2.200
 neighbor 192.0.2.1 remote-as 64000
 address-family ipv4 unicast
  default-information originate
  neighbor 192.0.2.1 activate
```

It should be noted that searching `ccp branch -a 'router bgp'` is a special
case that is local to the CLI script.

```{eval-rst}
.. note::

   When searching with only one branch  search term, this is a special case of
   the CLI script.  If you only use one branch search term, all configuration
   children matching the configuation parent will be shown (the parent is
   included as well).

```

## Example 5: Find IP addresses within a CIDR range

`ccp ipgrep` can find IP addresses in a CIDR range. By default,
`ccp ipgrep` splits words on whitespace and checks whether a word is an IP
address and that it falls within the requested CIDR range.

For instance, assume we have the following file contents:

```none
This file contains the addresses: 172.16.1.1 172.16.1.1 and 172.16.1.2
```

If you run this command, you'll get both IP addresses printed to
STDOUT: `ccp ipgrep -s 172.16.1.0/24 path/to/file.txt`.

```none
$ ccp ipgrep -s 172.16.1.0/24 path/to/file.txt
172.16.1.1
172.16.1.1
172.16.1.2
$
```

As you see, you can get duplicate IP addresses unless you
use `ccp ipgrep -u -s 172.16.1.0/24 path/to/file.txt`. The
`-u` option stands for `--unique`.

The default mode is just listing the IP addresses, but you can also
get matching lines
with `ccp ipgrep -l -s 172.16.1.0/24 path/to/file.txt`.

All the options for `ccp ipgrep` are:

```none
$ ccp ipgrep -h
usage: ccp ipgrep [-h] [-s SUBNETS] [-w WORD_DELIMITER] [-l | -u] [ipgrep_file]

options:
  -h, --help            show this help message and exit

required:
  ipgrep_file           Grep for IPs in these files, defaults to STDIN.
    -s SUBNETS, --subnets SUBNETS
                        Comma-separated IPv4 and/or IPv6 addresses or prefixes,
                        such as '192.0.2.1,2001:db8::/32'. If the mask is not
                        specified, a host-mask assumed.

optional:
  -w WORD_DELIMITER, --word_delimiter WORD_DELIMITER
                        Word delimiter regular expression, defaults to all whitespace.
                        Join multiple regex delimiters with a pipe character.
  -l, --line            Enable line mode (return lines instead of only returning the IP)
  -u, --unique          Only print unique IPs (remove duplicates)
```
