-2

I've seen a few answers to similar questions here, but non seem to address my specific issue.

I have a bash script which generates a list of variables that I want sent within an awk command. My issue is, that as soon as there more than one variables that I am trying to inject, awk throws a "unexpected newline or end of string" error. I've distilled the problem down to the following 2 lines of code:

MYVARS="VAR1=1; VAR2=2;"    
awk '{'$MYVARS'}'

So if I run:

MYVARS="VAR1=1;"    
awk '{'$MYVARS'}'

all is fine.

Can someone please explain what is going on, and preferably how to achieve what I want?

Please note that whilst this is similar to other questions - this is unique in so far as I am attempting to use a single bash variable to pass in multiple awk variables. Please do not close this question unless the question you direct me to specifically deals with this problem. My code works fine if I pass in a single variable.

paul frith
  • 551
  • 2
  • 4
  • 21
  • It should be: `awk -v VAR1="$VAR1" -v VAR2="$VAR2" '...'` – anubhava Oct 10 '22 at 20:02
  • Hopefully you'd never write C code where a function sets a bunch of variables that are used in a sub-function it calls as that'd obviously break cohesion and introduce tight coupling, both of which are indicators of bad software, vs passing in the data as argument(s) to the sub-function. What you're asking how to do here is the same thing - having your shell populate a bunch of awk variables used in an awk script it calls. Pass in the data and let the awk script populate whatever variables it needs however it has to do it from that data. – Ed Morton Oct 11 '22 at 14:39
  • Having said that - the question I closed this as a dup of does contain the information on how to do what you're trying to do by using ENVIRON or ARGV and creating the MYVARS shell variable as an array rather than a scalar. – Ed Morton Oct 11 '22 at 15:03

1 Answers1

1

Addressing the syntax issue ...

MYVARS="VAR1=1; VAR2=2;"    
awk '{'$MYVARS'}'

Is evaluated as 3 separate commands since the semicolon is processed as a bash command delimiter.

awk '{'VAR1=1; VAR2=2;'}'
^^^^^^^^^^^^^                   1st command
             ^                  1st command terminated
               ^^^^^^           2nd command
                     ^          2nd command terminated
                      ^^^       3rd command

And since the 1st command is invalid awk syntax the error is generated.

OP hasn't provided the full error message but on my system the above generates:

$ awk '{'$MYVARS'}'
awk: cmd. line:1: {VAR1=1;
awk: cmd. line:1:         ^ unexpected newline or end of string
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • That makes sense, but given that ";" also separates commands in awk, how do I escape it in bash? I've tried `MYVARS="VAR1=1\; VAR2=2\;"` but I then get error `^ backslash not last character on line` – paul frith Oct 10 '22 at 20:29
  • your question has been closed as a 'duplicate' .... see the [accepted answer](https://stackoverflow.com/a/19075707) for an assortment of ways to feed your `bash` variables to `awk` ... in this particular case you could probably get by with double quotes around the `bash` variable reference, eg: `awk '{ "$MYVARS" '}'` though other methods are going to be cleaner – – markp-fuso Oct 10 '22 at 20:43
  • The accepted answer still does not address my issue of having a single bash variable that contains a string which itself contains multiple variables that I want to set in awk. I have set single bash variables many times in awk. Please reopen, answer the actual question, point me to an answer which does, or give me a reason why what I am attempting is not possible. – paul frith Oct 10 '22 at 20:55
  • the section that starts with `Variable within the code`, and which I highlighted in my last comment (ie, wrap `bash` variable reference in double quotes), works; another alternative (not covered in the accepted answer) is to feed `MYVAR` into `awk` as a single `-v` variable and then parse the contents in a `BEGIN{}` block; another alternative: feed to `awk` as a single-line file and have a `FNR==NR {}` block parse the line – markp-fuso Oct 10 '22 at 21:01