2

I am working on a script and it would really help me, in this context, if I could see a dump of all the script defined variable names and values. Here's an example:

foo="1"
bar="2"

print_script_variables 

baz="3"

print_script_variables 

This would output:

foo="1"
bar="2"

foo="1"
bar="2"
baz="3"

Does something like print_script_variables exist? I have a feeling parsing the scripts you are executing is a fools errand.

If this doesn't exist, I would just type out a bunch of echo commands by hand. That's kind of annoying, because I'd like move where put print_script_variables as I troubleshoot without having to worry about which variables go in and out of scope.

This is a bash script, but I use zsh in my terminal, so something that would work in both would be ideal.

4
  • 3
    declare -p would do that but also include environment variables inherited by the script
    – muru
    Mar 25, 2022 at 5:58
  • @muru if that's the best thing that exists, it's better than echoing everything by hand, right? That could be an answer, but I'm hoping there's a better one out there. Maybe I could create a script to remove the lines that are env variables. Mar 25, 2022 at 6:00
  • 1
    diff <(export) <(declare -p) will output a different superset of variables, but I don't know of a way to get only the ones you want. It may be possible to build something out of these components. Mar 25, 2022 at 7:25
  • You could also use something simple like set | grep '^[a-z]' if your variables by convention start with a lowercase character.
    – jrw32982
    Apr 1, 2022 at 1:59

3 Answers 3

5

Adding to muru's reply, you could store the names of environment variables at the start to the script, and filter out the environment variables whenever the print_script_variables function is invoked. For a POSIX compliant way to do so, use the set utility to list all variables at the start of the script and store those in a temporary file. When the function print_script_variables is invoked, use diff to filter out the variables you don't need, i.e.,

# invoke at script start
set > /tmp/file1 # assuming /tmp/file1 is a safely generated temporary file
trap 'rm -f /tmp/file1' INT TERM HUP EXIT # delete the file on SIG{INT,TERM,HUP} and EXIT
print_script_variables() {
    # suppress lines unique to file1 and lines present in pipe (set output)
    # that it outputs only lines added to file1, i.e. new variables
    set | comm -13 /tmp/file1 - # edited; thanks to Martin for helping to save an extra file;
}
variable=20
print_script_variables

Edit

As you need a way to automatically execute the first line, you can use the dot (or source) utility for automatically executing the line at the start of a script. You should store the first line and the function definition in a file, say print_script_variables:

set > /tmp/file1
trap 'rm -f /tmp/file1' INT TERM HUP EXIT
print_script_variables() {
    set | comm -13 /tmp/file1 -
}

and source that file at the start of your script like so

. print_script_variables

variable=20
print_script_variables()
8
  • 1
    That's extremely clever and simple. Would there be any way of automatically executing that first line when any script is started? That way, I wouldn't have to refer back to the implementation of an exported print_script_variables if I want to remember how to use it. (This might be a really stupid ask, sorry.) Mar 25, 2022 at 8:29
  • 2
    I was going to offer what turns out to be a very similar suggestion. I would create a function "dump variables()` that took a parameter. "init" would initialise the temporary file, ""print" or nothing would dump the differences, "end" would delete the temporary file. But fundamentally the solution is the same so little point offering it as a separate answer. +1 Mar 25, 2022 at 8:56
  • 1
    I've not yet tried it out, but would something along the lines of set | comm -13 /tmp/file1 - work and save the extra temporary file?
    – user516667
    Mar 27, 2022 at 21:30
  • 1
    @DanielKaplan unfortunately process redirection is a non-POSIX feature so it wouldn't be supported across all machines. even more unfortunate is that the trap utility isn't a feature in POSIX anymore, so you can't automatically remove the temp file if the script is interrupted.
    – SeetheMoar
    Mar 27, 2022 at 23:34
  • 1
    @DanielKaplan Hey! It's actually still possible to use trap in POSIX, just that they changed the POSIX specification website to a PDF-like format using anchors from the original normal WWW document and worst of all, the search engine they provide is bad. I've updated the answer to delete the file when the script itself (the running script) receives any one of death signals. The only thing you'll need is an alternative to the mktemp utility to generate a random filename in /tmp/ directory.
    – SeetheMoar
    Mar 28, 2022 at 1:17
1

Here's another option that uses grep to filter out inherited vars.

#!/usr/bin/env bash

# Store names of inherited variables (by definition, exported)
readonly GREP_FILTERS=$(env | cut -d= -f1 | xargs printf " -e %s" )

print_script_vars() {
  declare -p | grep -v -E $GREP_FILTERS
}

Use declare -p if you want to see all shell variables, or env if only interested in exported vars.

0

Improved code by Adam Mlodzinski

#!/bin/sh

# Store names of inherited variables (by definition, exported)
readonly GREP_FILTERS=$(env | cut -d= -f1 | xargs printf " -e %s" )

print_script_vars() {
  declare -p | grep -v -E $GREP_FILTERS | sed 's/declare -[^ ]\{1,2\} //' | grep =
}

variable=20


print_script_vars
3
  • 1
    Please suggest this as an edit to Adam Mlodzinski’s answer (and explain how it improves that). Jan 31 at 16:27
  • @StephenKitt I have a meta question. If DenisVS edits this answer to explain how it improves on Adam Mlodzinski's, would that justify its separate existence; as far as I know, I wouldn't be notified of the edit so I'd be missing out. Jan 31 at 23:31
  • A comment to the edited answer should produce a notification. OP should always be notified of that AFAIK. Feb 12 at 10:12

You must log in to answer this question.

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