inserting variables within my awk statement - bash

Here is a snippet of my awk statement..I'm trying to insert these 2 variables in the statement but they are not getting evaluated. Can someone point me in the right direction?
ZONE=`date "+%Z %Y"`
DAY=`date "+%a"`
awk '{if (NR<2) {print "["$1, $2, $3"]"}}'
I'm trying this:
awk '{if (NR<2) {print "[" $DAY, $1, $2, $3, $ZONE "]"}}'
This tip here helped solve my problem.
Protect the shell variables from awk by enclosing them with "'" (i.e. double quote - single quote - double quote).
awk '{print "'"$VAR1"'", "'"$VAR2"'"}' input_file

You can use -v option:
ZONE=`date "+%Z %Y"`
DAY=`date "+%a"`
awk -vzone="$ZONE" -vday="$DAY" 'BEGIN { print zone, day }'

Those variables won't be expanded where they're enclosed in single quotes. Consider using double quotes for your outermost quotes and escaped double quotes inside your awk expression.
I'm only guessing here, though, as you do not appear to have included the actual command you used where your variables have been embedded, but aren't being evaluated.
In the future, or if this answer doesn't help, consider including the command you use as well as its output and an explanation of what you expected to happen. This way, it'll be much easier to figure out what you mean.

I liked yazu's answer above, although to get this to work on my MaxOSX (BSD) environment I had to tweak the syntax:
~ $ ZONE=`date "+%Z %Y"`
~ $ DAY=`date "+%a"`
~ $ awk -v zone="$ZONE" -v day="$DAY" 'BEGIN { print zone, day }'
CEST 2018 Wed

Related

How do I pass the output of a command that contains quotes as an awk variable?

Looking to set a date variable withing awk but can't get the quoting or syntax right!
awk -v c=$i -v d="date +\"%D %r %Z\"" '{print d c }'
Consider instead:
awk -v d="$(date +'%D %r %Z')" 'BEGIN{print d}'
The changes here are:
Use $() to execute date and get the output back for the variable d.
Using single quotes for the date format so you don't have double quotes in double quotes
Using BEGIN to execute the print statement in awk. This isn't necessary if you are feeding a file or stdin to awk for it to read records.

Why Does Running Awk With Double Quotes Break But Works With Single Quotes?

I noticed when running a command that this statement doesn't recognize the delimiter
awk -F',' "{print $4}" wtd.csv
However, this one does.
awk -F',' '{print $4}' wtd.csv
Any reason why? I'm sure this is part of some general bash rule I'm forgetting.
If you're using double quotes, $4 will get replaced by Bash (probably with the empty string). You'd need to escape the $ to use it in double quotes.
Example where this also is happening:
[thom#lethe ~]$ echo '$4'
$4
[thom#lethe ~]$ echo "$4"
[thom#lethe ~]$ echo "\$4"
$4
You are forgetting that double-quotes allow bash variable interpolation. In this case it tries to replace $4 with the fourth argument to the shell which is usually empty.
The single-quotes prevent bash interpolation and passes the literal $4 to awk.
You'll have identical results with:
awk -F',' '{print $4}' wtd.csv
awk -F',' "{print \$4}" wtd.csv

How to pass a bash variable into awk

I have a variable that is created in bash, and want to use it within awk statement to create a file by concatenating it with a string for the filename.
awk -v value="${index}" 'BEGIN{}{print $9 >> "example_value.txt";}END{}'
How can I do this?
You have to use it outside of the double quotes. awk concatenates it without any other character:
awk -v value="${index}" 'BEGIN{}{print $9 >> "example_" value ".txt";}END{}'
You could use -voption as in the examples previously posted.
Or you could just use something like :
awk 'BEGIN{}{print $9 >> "example_'"$index"'.txt";}END{}'
Moreover, you don't have to use {} around the variable index in this case.

How to use awk variable in search?

How to use awk variable in search?
Name="jony"
awk -v name="$Name" '/name/ {print $0}' file
this will search for string name, not for $Name which is actually jony.
Correct, awk won't recogize variables in / /. You can do:
Name="jony"
awk -v name="$Name" '$0 ~ name' file
Since print is awk's default behavior we can avoid using it here.
Hope I understood problem correctly:
Why wont you try following one:
awk '/'"$Name"'/ { print } ' testfile
When writing an AWK one-liner, you could quote the script with either the single quotes or double quotes. In the latter case the shell does all the substitution directly so that you do not need to pass the variable into the script via -v option:
Name="jony"
awk "/$Name/" file
# this works. after shell has performed substitutions, the line looks like
awk "/jony/" file
[bad!] Or even without quotes if the name does not contain spaces:
awk /$Name/ file
All the simplicity vanishes as soon as you want to use $ in the script, including awk special variables that use $0, $1, etc, because you will have to escape the dollar sign to prevent shell variable expansion.
awk "/$Name/ {print \$0}"
In addition you will have to escape the double quotes to add literal text to the script. Looks clumsy:
awk "/$Name/ {print \"Found in: \" \$0}"
To crown it all, negating regular expression with double quotes will cause a shell error:
awk "!/$Name/"
#error> ... event not found ...
The error will happen if $Name itself contains ! sign. This makes using double quotes unreliable.
So, to be on the safe side, prefer single quotes :)

how to pre-construct awk statement to pass to awk on command line?

I have a shell script that constructs an awk program as a string then pass that string to awk. This is because I want to use values of shell variables in the awk program.
My code looks like this:
awk_prog="'{if (\$4~/$shell_var/) print \$1,\$2}'"
echo $awk_prog
awk $awk_prog $FILENAME
However, when I pass the string to awk, I always get the error:
'{if ($4~/regex/) print $1,$2}'
awk: '{if
awk: ^ invalid char ''' in expression
What does that error message mean? I tried the -F: switch but it does not help. How can I settle this issue?
Thank you.
This is caused by shell quoting. The following will work:
awk_prog="{ if (\$4 ~ /$shell_var/) print \$1, \$2 }"
echo "$awk_prog"
awk "$awk_prog" $FILENAME
When you run awk '{ print }' foo from the command line, the shell interprets and removes the quotes around the program so awk receives two arguments - the first is the program text and the second is the filename foo. Your example was sending awk the program text '{if ...}' which is invalid syntax as far as awk is concerned. The outer quotes should not be present.
In the snippet that I gave above, the shell uses the quotes in the awk_prog= line to group the contents of the string into a single value and then assigns it to the variable awk_prog. When it executes the awk "$awk_prog"... line, you have to quote the expansion of $awk_prog so awk receives the program text as a single argument.
There's another way to get your shell variable into awk -- use awk's -v option:
awk -v pattern="$shell_var" '$4 ~ pattern {print $1, $2}' "$FILENAME"
Use -v multiple times if you have several variables to pass to awk.
If you truly want to hold your awk program in a shell variable, build it up using printf:
awk_script="$( printf '$4 ~ /%s/ {print $1, $2}' "$shell_var" )"
awk "$awk_script" "$FILENAME"
Note the use of quotes in the printf command: single quotes around the template to protect the dollar signs you want awk to interpret, double quotes for shell variables.
Another (IMO simpler) solution which (I think) addresses what you are intuitively trying to do is simply to use eval. You want the shell to behave as if you had literally typed:
awk '{if ($4~/foo/) print $1,$2}' path
(where foo and path are the literal contents of $shell_var and $FILENAME). To make that happen, just slap an eval on the front of your last line (and perhaps quotes for good measure, but they aren't necessary in this case) so that your last line is:
eval "awk $awk_prog $FILENAME"

Resources