0

I'm looking for some help in parsing a substring from the output of a command.

The output of the command looks like this (command is cerbot-auto certificates and related to letsencrypt certificates:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: amadev.domain1.com
    Domains: amadev.domain1.com rcpdev8.domain1.com 
    Expiry Date: 2019-05-12 14:51:44+00:00 (VALID: 87 days)
    Certificate Path: /etc/letsencrypt/live/amadev.domain1.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/amadev.domain1.com/privkey.pem
  Certificate Name: amadev.domain2.com
    Domains: amadev.domain2.com rcpdev8.domain2.com
    Expiry Date: 2019-05-07 13:12:11+00:00 (VALID: 82 days)
    Certificate Path: /etc/letsencrypt/live/amadev.domain2.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/amadev.domain2.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

I'm looking to extract the certificate name and the domains but am struggling the with the bash substring commands. I think I should be able to get what I need using cut and then manipulating that result but I haven't been successful yet.

It doesn't matter to me if I end up with an array of some sort with all values or if the code loops and does each one individually overwriting the previous but I need something that ends up with variables holding values that look like this:

certificate="amadev.domain1.com"
domains="amadev.domain1.com,rcpdev8.domain1.com"

Thanks in advance.

Ryan Price
  • 315
  • 6
  • 17

3 Answers3

1

A simple grep/cut solution :

cerbot-auto certificates | grep -E 'Certificate Name|Domains' | cut -d':' -f2
nullPointer
  • 4,419
  • 1
  • 15
  • 27
0

Try this (Shellcheck-clean) pure Bash code:

#! /bin/bash

# Regular expressions to match the required fields
name_rx='^Certificate[[:space:]]+Name:[[:space:]]+(.*)$'
domains_rx='^Domains:[[:space:]]+(.*)$'

certbot_auto_output=$(certbot-auto certificates)

# (Assuming a standard $IFS) 'read' will strip leading and trailing whitespace
while read -r line ; do
    if [[ $line =~ $name_rx ]] ; then
        certificate=${BASH_REMATCH[1]}
    elif [[ $line =~ $domains_rx ]] ; then
        domains=${BASH_REMATCH[1]}
        domains=${domains// /,}     # Replace spaces with commas
        printf 'certificate="%s"\n' "$certificate"
        printf 'domains="%s"\n' "$domains"
    fi
done <<<"$certbot_auto_output"

See mkelement0's excellent answer to How do I use a regex in a shell script? for information about using Bash regular expressions.

See Substituting part of a string (BashFAQ/100 (How do I do string manipulation in bash?)) for information about ${var//.../...}.

See Command line: <<< instead of << for information about <<<"..." ("here string").

pjh
  • 6,388
  • 2
  • 16
  • 17
0

Used funkyjelly's response to come up with the following:

# Store each certificate name and list of domains in an array
mapfile -t certificate_names < <(/opt/certbot-auto certificates | grep 'Certificate Name:' | cut -d':' -f2) 
mapfile -t domains < <(/opt/certbot-auto certificates | grep 'Domains:' | cut -d':' -f2) 

len=${#certificate_names[@]}

for (( i=0; i<$len; i++ ))
do
    #replace spaces with commas and drop the first comma
    fqdns=${domains[$i]}
    fqdns=${fqdns// /,}
    fqdns="${fqdns:1}"

    # Renew the cert
    /opt/certbot-auto certonly --manual --agree-tos --manual-public-ip-logging-ok --email oueemail@example.com --preferred-challenges dns --manual-auth-hook update-txt-records.sh --manual-cleanup-hook clean-txt-records.sh --cert-name ${certificate_names[$i]} -d $fqdns --expand --noninteractive

done
Ryan Price
  • 315
  • 6
  • 17