3

Assuming that i passed some variables to the awk script:

$AWK -f script.awk -v var01="foo" var02="bar"

And inside the script i obtain some pattern:

# pattern01 var01
/pattern01/ {
        if (??? == "foo") print
}

I want to expand the variable "$2" ("var01") to its given value. I have been trying with gawk and it seems to be able to expand variables in the following way:

print $$x

But this, for some reason, doesn't work in the first example, also i need to keep POSIX compatibility. Is it possible to expand the variable in the given example? (Note: I want specifically this behavior (if possible), so i don't want workarounds with other tools or shell expansion)

Equivalent in shell:

file01:
        foobar
        some random text
        pattern01 var01
        more random text...

code.sh:
        #!/bin/sh
        var01="Hello"
        x="$(grep '^pattern01' file01 | awk '{print $2}')"
        eval echo "$"$x # prints Hello
MayAccer
  • 43
  • 5
  • because i am printing the found pattern, which in the given example would be "pattern01 var01": $1="pattern01", $2="var01" – MayAccer Nov 27 '19 at 01:49
  • @MayAccer, is `var02` a shell variable? Could you please provide more information on this one please. – RavinderSingh13 Nov 27 '19 at 02:05
  • "var02" is a variable defined by the flag "-v", then the awk script is called to process some file, this file may have some pattern followed by the string "var01/var02", i want to transform that string in the variable with same name. (i will edit and add the equivalent in shell script) – MayAccer Nov 27 '19 at 02:13
  • Just use the variable by its name just like you would in C, etc. e.g. `print var01`. – Ed Morton Nov 27 '19 at 02:21
  • The content of the variable should be printed if, and only if, it appears inside some pattern, so i will have its name only after obtaining some pattern – MayAccer Nov 27 '19 at 02:24
  • Using variable in `awk` see this post: https://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-script/19075707#19075707 – Jotne Nov 27 '19 at 06:22

3 Answers3

1

I have found one solution, by setting the variable as part of the environment and then calling the special variable "ENVIRON" with the name (as it acts as a dictionary):

# pattern01 var01
/pattern01/ {
        if (ENVIRON[$2] == "foo") print
}

I think that by creating manually the dictionary at the BEGIN stage, the same behaviour could be achieved without making use of the environment.

MayAccer
  • 43
  • 5
1

Using POSIX awk, there is no way to lookup the value of a variable by it's name. Instead consider using an array to store the values. Not the most elegant, but portable:

$AWK -e 'BEGIN { v["var01"] = "foo" ; v["var02"] = "bar" }' -f script.awk

script.awk

# pattern01 var01
/pattern01/ {
        if ( v[$2] == "foo") print
}

If you know that you will be new GNU AWK version, and OK with using extensions, you can use the SYMTAB array. From man page:

SYMTAB An array whose indices are the names of all currently defined global variables and arrays in the program. The array may be used for indirect access to read or write the value of a variable:

  foo = 5
  SYMTAB["foo"] = 4
  print foo    # prints 4
$AWK -f script.awk -v var01="foo" var02="bar"

script.awk
# pattern01 var01
/pattern01/ {
        if ( SYMTAB[$2] == "foo") print
}

Both approached eliminate the need to create environment variables, which may have impact on other programs, and may be hard to scale.

dash-o
  • 13,723
  • 1
  • 10
  • 37
  • As i expected a dictionary is the only portable (at least from what i have tested) solution. In my case the environment is cleaned, but this solution is less error prone, so i will mark as better solution. – MayAccer Nov 29 '19 at 06:28
0

Can you try this

var01="Hello"
x="$(grep '^pattern01' file01 | awk '{print $2}')"
echo ${!x}

hope this helps.. Thanks,

  • Would work in shell script (specifically bash), and in a better way than using "eval". But the problem weren't to achieve this behaviour in shell script – MayAccer Nov 29 '19 at 06:24