This code and updates are available on Github.
I've written a small utility to dump the variables that are assigned in a bash script.
Please note:
- This script depends on the shfmt and jq apps.
- I am not looking to make this script posix compliant, only bash specific.
Some possible areas for improvement:
- Can the jq query be improved?
- Are there other entries in the json output of shfmt that I can look for variable assignments.
- Any gotchas I'm missing?
As I type out this question, it occurs to me that showing variables used in a script would be a good thing to allow as an option. I'll look into it, but if anyone has any ideas in this respect, I'm interested in hearing your input.
#!/bin/bash
#------------------------------------------------------------------------------
warn() { printf '%s\n' "$*" >&2; }
die() {
(($#)) && warn "$*"
exit 1
}
command_exists() { command -v "1ドル" &> /dev/null; }
#------------------------------------------------------------------------------
_showvars() {
local filename=1ドル
[[ -f $filename ]] || die "$filename is not a file or does not exist."
[[ -r $filename ]] || die "$filename is not readable."
jq_query='[ .. | select(.Assigns?) | .. | select(.Name?) | .Name.Value ] | unique[]'
# shellcheck disable=SC2046
printf ' %s\n' $(shfmt -tojson < "$filename" | jq "$jq_query" | tr -d '"')
}
#------------------------------------------------------------------------------
(($#)) || {
cat << EOH
showvars is a simple script that shows
what variables are assigned in a bash
script
usage: showvars filename [filename ...]
EOH
exit 1
}
for r in shfmt jq; do
command_exists $r || die This script depends on $r and it is not found.
done
for f in "$@"; do
printf '\n%s:\n' "$f"
_showvars "$f"
shift
done
echo
Edit: Fixed copy-paste error with (($#))...
line
Edit: Removed code that removes lower case variables (an artifact from another code solution)
-
1\$\begingroup\$ Please see What to do when someone answers. I have rolled back Rev 4 → 3 \$\endgroup\$Sᴀᴍ Onᴇᴌᴀ– Sᴀᴍ Onᴇᴌᴀ ♦2019年08月01日 18:16:41 +00:00Commented Aug 1, 2019 at 18:16
1 Answer 1
The difference between $*
and $@
warn() { printf '%s\n' "$*" >&2; }
This is equivalent to the simpler:
warn() { echo "$*" >&2; }
The printf
version is useful if you want to produce one line per parameter,
and in that case you must use "$@"
instead of "$*"
.
Also in callers of warn
.
Use -r
for raw output of jq
Instead of jq "..." | tr -d '"'
a better way is jq -r "..."
.
An alternative to printf
and a sub-shell
Instead of this:
# shellcheck disable=SC2046 printf ' %s\n' $(shfmt -tojson < "$filename" | jq "$jq_query" | tr -d '"')
I recommend this way (and no need to disable shellcheck):
shfmt -tojson < "$filename" | jq -r "$jq_query" | sed -e 's/^/ /'
Use a bit more double-quotes
You did a good job of double-quoting the most important things. I would double-quote here too:
command_exists $r || die This script depends on $r and it is not found.
To train good habits:
command_exists "$r" || die "This script depends on $r and it is not found."
"$@"
is the default list for for
Instead of for f in "$@"; do
, you can simply write for f; do
.
The shebang
In some systems Bash is not in /bin/bash
.
For that reason I prefer to use #!/usr/bin/env bash
as the shebang, it makes the script more portable.
Simplify the readable file check?
[[ -f $filename ]] || die "$filename is not a file or does not exist." [[ -r $filename ]] || die "$filename is not readable."
The -r
implies -f
. I would simplify this to one line:
[[ -r $filename ]] || die "$filename is not a readable file."
Use echo
when it's good enough
Instead of printf '\n%s:\n' "$f"
I would write:
echo
echo "$f:"
Here-documents
EOH
is an unusual symbol for the here-document marker.
That's not a problem, but I think the less surprising elements in a script,
the better.
I don't see a good reason to not call this EOF
as usual.
Your questions
Some possible areas for improvement:
- Can the jq query be improved?
- Are there other entries in the json output of shfmt that I can look for variable assignments.
Unfortunately I'm not able to answer these. You might want to wait for another reviewer who can!
-
\$\begingroup\$ Thank you. I implemented some of your suggestions, while others prompted a different change. I've included details in my question. \$\endgroup\$harleypig– harleypig2019年08月01日 18:14:39 +00:00Commented Aug 1, 2019 at 18:14