Search code examples
bashvariablesawkgrepalias

bash resolve aliases and variables


I have various lines in my profile like this:

alias x='ls -al'; alias y='df -kh' # etc

I have various lines that define variables:

xx='name'; yy='stuff'

If I make a typo for an alias and don't put the word alias before it, then it will simply define a variable and not generate an error, e.g. y='df -kh'.

Is there a way with grep or awk to parse a script to find all definitions that don't have alias before them (so that I can determine if they were supposed to be an alias or a variable declaration)? i.e. find anything that looks like a variable that does not have alias written before it?


Solution

  • $ cat defs
    alias x='ls -al'; alias y='df -kh' # etc
    xx='name'; yy='stuff'
    

    $ cat diffsets
    #!/bin/bash
    
    # Restart with a clean environment in case the file has been sourced
    # previously. We need the absolute path in the shebang above for this.
    [[ -v HOME ]] && exec -c "$0" "$@"
    
    # We must use full paths without variables in case those variables
    # are also set in the file we're about to source.
    [[ -s "$1" ]] &&
    mkdir -p "/usr/tmp/diffsets_$$" &&
    trap '
        rm -f "/usr/tmp/diffsets_$$/old" "/usr/tmp/diffsets_$$/new" &&
        rmdir "/usr/tmp/diffsets_$$"
    ' 0 &&
    
    # We want to only compare variables, not function definitions, but we
    # can't use `set -o posix` as we need newlines printed as $'\n' instead
    # of literal newline chars for later comparison so ensure posix is disabled
    # and use awk to exit when the first function is seen as they always are
    # printed after variables.
    
    set +o posix &&
    set | awk '$NF=="()"{exit} 1' > "/usr/tmp/diffsets_$$/old" &&
    
    . "$1" &&
    
    set +o posix &&
    set | awk '$NF=="()"{exit} 1' > "/usr/tmp/diffsets_$$/new" &&
    
    comm -13 "/usr/tmp/diffsets_$$/old" "/usr/tmp/diffsets_$$/new"
    

    $ ./diffsets defs
    xx=name
    yy=stuff
    

    I'm specifically not using variables to hold the set output for comparison nor using mktemp to create the temp files (which would require variables to hold the mktemp output) as anything using variables in this script would fail if the file being sourced (defs in this case) contained a definition for those variables.