Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify a shell variable inside awk block of code

Is there any way to modify a shell variable inside awk block of code?

--------- [shell_awk.sh]---------------------
 #!/bin/bash

shell_variable_1=<value A>
shell_variable_2=<value B>
shell_variable_3=<value C>

awk 'function A(X)
{ return X+1 }
{ a=A('$shell_variable_1')
  b=A('$shell_variable_2')
  c=A('$shell_variable_3')
  shell_variable_1=a
  shell_variable_2=b
  shell_variable_3=c
}' FILE.TXT
--------- [shell_awk.sh]---------------------

This is a very simple example, the real script load a file and make some changes using functions, I need to keep each value before change into a specific variable, so then I can register into MySQL the before and after value.

The after value is received from parameters ($1, $2 and so on).

The value before I already know how to get it from the file.

All is done well, except the shell_variable been set by awk variable. Outside from awk block code is easy to set, but inside, is it possible?

like image 692
Sirius Avatar asked Nov 16 '25 11:11

Sirius


1 Answers

No program -- in awk, shell, or any other language -- can directly modify a parent process's memory. That includes variables. However, of course, your awk can write contents to stdout, and the parent shell can read that content and modify its own variables itself.


Here's an example of awk that writes key/value pairs out to be read by bash. It's not perfect -- read the caveats below.

#!/bin/bash

shell_variable_1=10
shell_variable_2=20
shell_variable_3=30

run_awk() {
        awk -v shell_variable_1="$shell_variable_1" \
            -v shell_variable_2="$shell_variable_2" \
            -v shell_variable_3="$shell_variable_3" '
        function A(X) { return X+1 }
        { a=A(shell_variable_1)
          b=A(shell_variable_2)
          c=A(shell_variable_3) }
        END {
          print "shell_variable_1=" a
          print "shell_variable_2=" b
          print "shell_variable_3=" c
        }' <<<""
}

while IFS="=" read -r key value; do
        printf -v "$key" '%s' "$value"
done < <(run_awk)

for var in shell_variable_{1,2,3}; do
  printf 'New value for %s is %s\n' "$var" "${!var}"
done

Advantages

  • Doesn't use eval. Content such as $(rm -rf ~) in the output from awk won't be executed by your shell.

Disadvantages

  • Can't handle variable contents with newlines. (You could fix this by NUL-delimiting output from your awk script, and adding -d '' to the read command).
  • A hostile awk script could modify PATH, LD_LIBRARY_PATH, or other security-sensitive variables. (You could fix this by reading variables into an associative array, rather than the global namespace, or by enforcing a prefix on their names).
  • The code above uses several ksh extensions also available in bash; however, it will not run with POSIX sh. Thus, be sure not to run this via sh scriptname (which only guarantees POSIX functionality).
like image 186
Charles Duffy Avatar answered Nov 18 '25 13:11

Charles Duffy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!