LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How to read shell variables in awk (https://www.linuxquestions.org/questions/programming-9/how-to-read-shell-variables-in-awk-4175431885/)

Thad E Ginataom 10-12-2012 12:52 PM

How to read shell variables in awk
 
I just wrote this in another thread, then realised it was not what the OP was asking <Blush> Might come in useful to someone...

Here's some basic information about getting command line parameters to a shell script into awk. You do it by manipulating quotes. Here's an example:
Quote:

awk ' BEGIN { a="'$1'"; b="'$2'"; c="'$3'"; print a, b, c; }'
It is the red single quotes that matter there. The double quotes just prevent syntax errors when one or more of the positional parameters is empty, and will result in awk doing a="" rather than trying to do a=;. Think hard about what those single quotes do!

Look:
Code:

$  cat xxx
awk ' BEGIN { a="'$1'"; b="'$2'"; c="'$3'"; print a, b, c; }'
 $  ./xxx 1 2 3
1 2 3

lets add my favourite debugging method so we can see clearly what the shell is doing and what awk is seeing:
Code:

$  cat xxx
set -xv
awk ' BEGIN { a="'$1'"; b="'$2'"; c="'$3'"; print a, b, c; }'
 $ 
 $  ./xxx frog pig dog
awk ' BEGIN { a="'$1'"; b="'$2'"; c="'$3'"; print a, b, c; }'
++ awk ' BEGIN { a="frog"; b="pig"; c="dog"; print a, b, c; }'
frog pig dog
 $


ntubski 10-12-2012 03:11 PM

You can save quoting effort with awk's -v option:
Code:

awk -va="$1" -vb="$2" -vc="$3" 'BEGIN { print a, b, c; }'

grail 10-12-2012 11:48 PM

Well maybe a little overkill, but here is another alternative:
Code:

#!/bin/bash

awk 'BEGIN{for(i=1;i<(ARGC - 1);i++){print "do stuff with",ARGV[i];ARGV[i]=""}}' "$@" file

Then simply run the shell script as normal:
Code:

./script.sh one two three

Thad E Ginataom 10-13-2012 03:10 AM

Ahh! ARGC and ARGV are the arguments to awk itself, and you have made the arguments to the shell script available by including $@ as the first argument.

It is elegant, and does not suffer the absolute dependency on getting the quotes right that my solution does. Getting those quotes right is not too bad on a one-liner, but can be a real headache in anything longer. Nice. Thanks.

David the H. 10-13-2012 12:45 PM

I also should point out that this is not quite safe as it stands:

Code:

awk 'BEGIN { a="'$1'"; b="'$2'"; c="'$3'"; print a, b, c; }'
    ^          ^  ^      ^  ^      ^  ^                  ^
    |===========|  |======|  |======|  |===================|

I highlighted the opening and closing quotes to make it clearer that the shell parameters have been left completely unprotected. If any of them contained multiple whitespace characters or globbing patterns that matched something in the current directory, you'd get incorrect expansion. This means that you need to include yet another set of double quotes to protect them.

Code:

awk 'BEGIN { a="'"$1"'"; b="'"$2"'"; c="'"$3"'"; print a, b, c; }'
Either that, or use double quotes to begin with, and backslash escape any quotes, dollar signs, or backslashes that need to appear in the expression itself (which can be quite a hassle in an awk script).

Code:

awk "BEGIN { a=\"$1\"; b=\"$2\"; c=\"$3\"; print a, b, c; }"
As you can see, it's really much easier and more readable to use awk's built-in variable importing feature.

Speaking of which, another option is the little-known feature in awk that lets you set up variables as arguments after the expression, and before the filename(s) that they apply to.

Code:

awk '{ print a, b, c }' a="$1" b="$2" c="$3" inputfile

Thad E Ginataom 10-13-2012 02:52 PM

Quote:

I highlighted the opening and closing quotes to make it clearer that the shell parameters have been left completely unprotected.
Yes. The point is that the single quotes indicate what "belongs" to the shell and what "belongs" to awk. To put it more formally, what is expanded by the shell before calling awk with the result --- and there are often dangers such as you mention.

I think I should have a signature: ten years out of date and relearning! Because it's true, and I only realised the danger of not using the first set of " when I saw the syntax errors.
Quote:

Speaking of which, another option is the little-known feature in awk that lets you set up variables as arguments after the expression, and before the filename(s) that they apply to.
I like this best of all so far. Thanks.


All times are GMT -5. The time now is 12:20 AM.