'Merge bash command(s)/simplification of a long command in bash

Hi I am making one script for which I would like it, that through one command it would be possible to make a more complex command or function. The problem is that I have three docker containers which have the same name but only the digit changes. And just the docker container has one entry in the logs and that is just the right Cloudflared URL, I need to get it through that sub-command or function more than 1 times. Because I have three docker containers and each would have a different url from the logs.

I know that via classic way it goes! Only problem is that if I repeat the same commands it creates a little mess in the script (at least that's how I feel).

#!/bin/bash
function test {
    docker_container_proxy_name="cloudflared"
    real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"
    docker_container_1_uri_outside="$(docker logs ${docker_container_proxy_name}1 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
    docker_container_2_uri_outside="$(docker logs ${docker_container_proxy_name}2 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
    docker_container_3_uri_outside="$(docker logs ${docker_container_proxy_name}3 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
}
test

Is there any way through which I can simplify it like the whole long command, but only the docker container digit changes. Into like this (more cleaner in my eye):

#!/bin/bash
function test {
    docker_container_proxy_name="cloudflared"
    real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"
    command="$(docker logs ${docker_container_proxy_name} 2>&1 | grep -Eo $real_domain_of_cloudflared | tail -n 1)"
    docker_container_1_uri_outside="${command}1"
    docker_container_2_uri_outside="${command}2"
    docker_container_3_uri_outside="${command}3"
}
test

I would be glad for an answer. Maybe a similar question already exists, but I admit I didn't look for it and went straight to write my question, and I apologize that maybe this will be a similar post.

Docker containers:

$ docker container ps | grep "cloudflared"
<id_of_container> cloudflare/cloudflared:2022.4.1-amd64 "cloudflared --no-au…" 11 days ago Up 2 days cloudflared3
<id_of_container> cloudflare/cloudflared:2022.4.1-amd64 "cloudflared --no-au…" 11 days ago Up 2 days cloudflared2
<id_of_container> cloudflare/cloudflared:2022.4.1-amd64 "cloudflared --no-au…" 11 days ago Up 2 days cloudflared1

#1 for XFCE_noVNC
#2 for filebrowser
#3 for code-server
#i want this services in my "pocket/everywhere" without my public ipv4.


Solution 1:[1]

Variables are for storing data, not executable code. Generally the best way to store executable code is in a function:

#!/bin/bash
get_container_uri() {
    docker_container_proxy_name="cloudflared"
    real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"
    docker logs "${docker_container_proxy_name}${1}" 2>&1 | grep -Eo "$real_domain_of_cloudflared" | tail -n 1
}

docker_container_1_uri_outside="$(get_container_uri 1)"
docker_container_2_uri_outside="$(get_container_uri 2)"
docker_container_3_uri_outside="$(get_container_uri 3)"

Note that the function just runs the docker logs ... command directly rather than capturing its output; that way that command's output becomes the function's output, which is exactly what's wanted.

Also, some general scripting recommendations: you should (almost) always put variable references in double-quotes (e.g. grep -Eo "$real_domain_of_cloudflared") to keep the shell from parsing them in unexpected ways. The function keyword is nonstandard; the standard way to define a function is by putting () after the name (as I did here). Don't use test as the name of a function, since that's the name of a rather important built-in command, and overriding it might break other things.

shellcheck.net will point out some of these (and many other common mistakes). I recommend running your scripts through it and fixing what it points out.

Solution 2:[2]

Almost correct:

Suggesting:

#!/bin/bash
docker_container_proxy_name="cloudflared"
real_domain_of_cloudflared="https://([a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60})(-[a-z0-9]{1,60}).trycloudflare.com"

function command {
    echo "$(docker logs "${docker_container_proxy_name}$1" 2>&1 | grep -Eo "$real_domain_of_cloudflared" | tail -n 1)"
}

function test {
    docker_container_1_uri_outside=$(command 1)
    docker_container_2_uri_outside=$(command 2)
    docker_container_3_uri_outside=$(command 3)
}
test

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Gordon Davisson
Solution 2