How to increment a shell variable in an awk action

awk, bash, linux, shell

Solution

Try this:

func() {
 awk '$1~/^pattern/ {++awk_var} END {print awk_var+0}' "$1"
}

shell_var=$(func input_file_name)

The shell and `awk` are separate worlds, and you should treat them as such(*) (which, in effect, you're already doing, by enclosing your `awk` program in single quotes, which prevents the shell from expanding any shell variable references in your `akw` program string).

Thus, use an `awk`[-internal] variable to perform your counting (`awk_var`) and output it after having finished processing the input file (in the `END` block, using `print` to output the `awk` variable to `stdout` - the `+0` part is to ensure that the output defaults to `0` in case NO match was found.)

Note that, generally, `awk` variables need no explicit initialization, because they default to `0` in numerical and Boolean contexts, and to `""` (empty string) in string contexts).

Also note that `awk` has its own syntax, and shell constructs such as `$((...))` for arithmetic expansion do not apply. Generally, `awk` variables are referred to just by name (no `$` prefix), and arithmetic operations such as `++` can be applied directly.

Using command substitution - `$(...)` - in the shell then allows you to capture output from the `awk` command.

In your specific case you have no need to pass variable values into the `awk` program, but if you needed to do that, you'd use one or more instances of `awk`'s `-v` option; e.g.: `awk -v awk_var="$shell_var" ...`

On the shell (`bash`) side, if you wanted to add `awk`'s output to the shell variable instead of just assigning it:

declare -i shell_var                # make sure variable is an integer
shell_var+=$(func input_file_name)  # add function's output to existing value

(*) The shell and `awk` have completely separate namespaces that have no direct way of interacting with one another: `awk` has no concept of shell variables, and the shell has no concept of `awk` variables.

It is technically feasible, but ill-advised to integrate shell variable VALUES into an `awk` program - by using a double-quoted string to represent the `awk` program in which you reference shell variable VALUES, which are then expanded by the shell ONCE, BEFORE the string gets passed as a program to `awk`. What you CANNOT do is to modify a shell variable from inside an `awk` program.

Since it gets complicated quickly as to which parts of the `awk` program are interpreted by the shell up front vs. which parts are interpreted by `awk` later (where `'$` has special meaning too, for instance), the best approach is to:

- use a single-quoted string to represent the `awk` program, so as to protect it from interpretation by the shell

- if values need to be passed in, use instances of the `-v` option

- if something needs to be passed out, print to `stdout` from `awk` and use command substitution or redirection to capture it via the shell.

Problem

My shell script is something like this: ``` #!/bin/bash global_var=0 func() { awk '$1 ~/^pattern/ {global_var=$((global_var+1))}' $1 } func input_file_name ``` I want to increment the global (shell) variable `global_var` inside the `awk` action. How to do so? Normal shell style incrementing does not seem to be working.

Original source