Patrick
Patrick

Reputation: 106

Regular expression to retrieve a string from a multiline file text

I am searching for a way to extract the peer IP by looking for the secret of that peer.

Example:

peer 1.2.3.10 {
    authentication {
        mode pre-shared-secret
        pre-shared-secret SecretPasswordA
    }
    connection-type initiate
    ike-group IKE_1.2.3.4
    local-address 6.7.8.9
    vti {
        bind vti64
        esp-group ESP_1.2.3.4
    }
}
peer 1.2.3.20 {
    authentication {
        mode pre-shared-secret
        pre-shared-secret SecretPasswordB
    }
    connection-type initiate
    ike-group IKE_1.2.3.4
    local-address 6.7.8.9
    vti {
        bind vti64
        esp-group ESP_1.2.3.4
    }
}
peer 1.2.3.30 {
    authentication {
        mode pre-shared-secret
        pre-shared-secret SecretPasswordC
    }
    connection-type initiate
    ike-group IKE_1.2.3.4
    local-address 6.7.8.9
    vti {
        bind vti64
        esp-group ESP_1.2.3.4
    }
}

Provided I know SecrePasswordB, I would need to retrieve the peer IP which is 1.2.3.20, of empty if not found (or anything else easy to identify.

The text comes from a shell command into a variable (ie. TEXT=$(command_string)).

As I only have a basic shell and few tool available on the system that would need to be done with very basic linux tools. And here I am stuck not finding a solution...

Upvotes: 1

Views: 86

Answers (2)

tshiono
tshiono

Reputation: 22012

Assuming you have a variable TEXT assigned to the whole lines provided as an example, would you please try:

secret="SecretPasswordB"        # or assign to your actual string
secret=$(printf %q "$secret")   # escape metacharacters just in case

pat='peer[[:blank:]]+(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3})[[:blank:]]*\{[^{]+authentication[[:blank:]]*\{[^}]+pre-shared-secret[[:blank:]]+'"$secret"

if [[ $TEXT =~ $pat ]]; then
    echo "${BASH_REMATCH[1]}"
fi

Output:

1.2.3.20

Please note that the regex above is tested against the given example only and may not be robust enough for an arbitrary input.

Upvotes: 2

jhnc
jhnc

Reputation: 16652

If the data is formatted into separate lines as shown in the question then a simple shell script suffices. Simply split input into a leading word followed by the rest. Save the IP whenever a "peer" line is read. Print the most recent IP if the secret is read.

getPeerIP:

#!/bin/sh

secret="$1"

while read -r arg1 rest; do
    case "$arg1" in
        peer)
            ip="${rest% *}" # prune everything after first space
            ;;
        pre-shared-secret)
            if [ "$rest" = "$secret" ]; then
                echo "$ip"
                exit # don't bother reading rest of file
            fi
            ;;
    esac
done

Usage:

command_string | getPeerIP 'Secret Password'

Upvotes: 1

Related Questions