0

I'm trying to create a script where pretty much things got sorted out earlier in it and I'm left with the booleans I need stored in variables. I just need to run them through one last loop and I'm done

This last part I'm talking about is a less readable version of something similar to this:

                         [↑continues on top↑]
var5="$(some long operation that has different results on different systems   )"
var6="$(bc of escaping or slighly different variations on the basic set of    )"
var7="$(UNIXy commands preloaded on every system's minimal installation       )"
var8="$(e.g: <grep> Um…what else…oh yeah!  The output of these is 1 or 0  🤓  )"

varlist='$var1 $var2 ... $var8'                # ←I assume 'this' would 
                                               #  prevent it from being expanded

for ENTRY in $varlist
do
  if [ "$ENTRY" ] # ←Already a boolean
  then
    <perform operation>
  else
    <log/echo it wasn't needed or something>
  fi
done

Would that work? Or rather — is it portable? I'm jumping from macOS*, Fedora, RHEL, Debian and "appliance" FreeBSD (pfSense, OPNsense, …) nonstop. That said, I do mean Fedora, RHEL, Debian, macOS and FreeBSD, no their derivatives/downstreams/whatever so things are very predictable and stable. The most I stray from these systems is Debian on WSL and only because SSH on PowerShell is very glitchy. Am I breaking rules? Do I need to enclose variables in the variables variable (varlist, I know you just know but to avoid ambiguities) in something else? Maybe escape the $?

If you have completely different alternatives to suggest, I'm listening. I'm open for anything as long as it still is Bash.


*: pre-Catalina still with Bash by default.

2 Answers 2

3

instead of numbered variables, use an array:

entries=(
    "$(some long operation that has different results on different systems   )"
    "$(bc of escaping or slighly different variations on the basic set of    )"
    "$(UNIXy commands preloaded on every system's minimal installation       )"
    "$(e.g: <grep> Um…what else…oh yeah!  The output of these is 1 or 0  🤓  )"
)
for entry in "${entries[@]}"; do
    echo "this is entry: $entry"
done

Works with the default bash 3.2 that ships with MacOS

Trying to stringify a list of strings and then separate them is destined to fail: see http://mywiki.wooledge.org/BashFAQ/050

1
  • I know you guys are pros and this is common sense but for newbies like me this is priceless, thanks! I actually had functions earlier in the script which are name in a PowerShell-like manner, so the for loop would expand something like export-"$entry" later. I tested it and it worked all and it work! I forgot about testing with echo though, it could've just as well gone south very fast. Thanks again!
    – Vita
    Nov 25, 2021 at 16:04
1

You should use the ${!name} syntax for variable indirection.

Bash uses the value of the variable formed from the rest of parameter as the name of the variable

So this would work:

    varnames='var1 var2 ... var8'
    for varname in $varnames
    do
        if [ "${!varname}" ]
        ...

As for portability, that will depend on the bash version in each of your environments.

3
  • variable indirection via ${!p} was in Bash 2.0 already (based on the list here), so it's probably available anywhere with Bash. But I don't think it's a thing any other shells, if that ever comes up.
    – ilkkachu
    Nov 24, 2021 at 17:59
  • Argh! I'm so conflicted bc this is quick and works dead on but I've just been told functions are for code, vars for data. I think I'll just cheat and pretend not to know about it. "Who? curly-what?! No that's not my code..." Already save it for reference in the drafts folder. Thanks!
    – Vita
    Nov 25, 2021 at 16:11
  • In the first place, programming is for getting work done. Purism is important if you want to reuse, change, maintain code, or pass it on to others.
    – db-inf
    Nov 25, 2021 at 20:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .