dynamically setting a makefile variable using awk - makefile

I have a variable stoppoint defined in my makefile.
I want to set this variable using the output of awk from withing my Makefile.
I want to see if the second argument is main or not
I have tried:
stoppoint = $(awk '$$2 ~ /main/ {print $$1}' file)
stoppoint = "$(awk '$$2 ~ /main/ {print $$1}' file)"
stoppoint = 'awk '$$2 ~ /main/ {print $$1}' file'
awk '$$2 ~ /main/ {print $$1}' file > stoppoint
awk '$$2 ~ /main/ {print $$1}' file > $(stoppoint)
However, I am unable to set this variable.
Kindly tell me how one can set a variable using awk inside a Makefile
PS: On command line, the awk command gives me the output I desire...
Thanks,
Tejas

You have to use french quotes (``)
Here is an example:
all:
#a=`echo "hello world!!" | awk '{print $0;}' -`; echo $$a;

You need to use an eval structure like this:
.PHONY: default
default: all
rule1:
$(eval GLOBAL_VAR=`awk '$$2 ~ /main/ {print $$1}' file`)
all: rule1
#echo "The global var is: $(GLOBAL_VAR)"
The eval evaluates the string as makefile syntax. Here, it sets the GLOBAL_VAR variable to the result of the shell function call, which in turn gets printed out in another rule to illustrate it's global.

The solution is simple:
Makefile assumed the format
target: dependencies followed on the next line by actions after a TAB
In the above case, we cannot set a variable in the next line after a TAB because it assumes it to be an action. Just remove the TAB and set it.
That would solve the issue

Right now the way I do it is:
#awk '$$2 ~ /main/ {print $$1}' inputfile > DUMP
It gives me a value 0x60000078 inside dump
And to use it:
#echo -e "set pc $(shell cat DUMP)" > testfile
This seems to solve my issue, But I hope someone can point me to a better solution.
Thanks,
Tejas

Another option for using awk in a makefile, use of $$:
VERSION=`awk '/version:/{print $$NF}' charts/Chart.yaml`

What I needed to work around this problem was using the keyword shell when calling awk, like that:
VARIABLE="$(shell awk '__awk script__' file-awk-processes)"
Hope it helps!

Related

Awk field values inside make file

I have a makefile, and I am trying to use awk in a one liner inside of it:
# makefile
...
SHELL := /bin/bash
my_rule:
ls dir | awk -v path=$(current_dir) '{print path"/"$1}' > some_file
however, I can't seem to get make to drop the $1 into awk. How do I escape/access the field variables in awk, within the makefile?
Try changing $ to $$ in makefile to make awk read it as correct field.
This should do it:
# makefile
SHELL := /bin/bash
my_rule:
ls dir | awk -v path=$(current_dir) '{print $$path"/"$$1}' > some_file

Assign bash variables from one awk command?

Hoping someone can help me make my awk commands more efficient please!
Let's say my text file has around 30 lines of this type of thing:
ENTIRE:11.3.28.4.0
OSVER:Solaris11
VARFREE:3G
I'm assigning these to variables in a bash script like this:
ENTIRE=$(awk -F\: '$1 ~ /ENTIRE/ {print $2}' $HOSTFILE)
RELEASE=$(awk -F\: '$1 ~ /RELEASE/ {print $2}' $HOSTFILE)
OSVER=$(awk -F\: '$1 ~ /OSVER/ {print $2}' $HOSTFILE)
Because I have around 30 of these, it means awk is run 30 times, which is slow, and clearly not the best way.
Can anyone suggest how I can build these into one awk command please?
Thanks in advance!
You don't need awk at all. If modifying the original file isn't an option, use a while loop and the declare command to define each variable.
while IFS=: read name value; do
declare "$name=$value"
done < "$HOSTFILE"
An example:
$ IFS=: read name value <<< "foo:bar"
$ declare "$name=$value"
$ echo "$foo"
bar

Shell command to retrieve specific value using pattern

I have a file which contains data like below.
appid=TestApp
version=1.0.1
We want to parse the file and capture the value assigned to appid field.
I have tried with awk command as below
awk '/appid=/{print $1}' filename.txt
However it outputs the whole line
appid=TestApp
but we required only
TestApp
Please let me know how I can achieve this using awk/grep/sed shell commands.
You need to change the field separator:
awk -F'=' '$1 ~ /appid/ {print $2}' filename.txt
or with an exact match
awk -F'=' '$1 == "appid" {print $2}' filename.txt
outputs
TestApp
There's about 20 different ways to do this but it's usually a good idea when you have name = value statements in a file to simply build an array of those assignments and then just print whatever you care about using it's name, e.g.:
$ cat file
appid=TestApp
version=1.0.1
$
$ awk -F= '{a[$1]=$2} END{print a["appid"]}' file
TestApp
$ awk -F= '{a[$1]=$2} END{print a["version"]}' file
1.0.1
$ awk -F= '{a[$1]=$2} END{for (i in a) print i,"=",a[i]}' file
appid = TestApp
version = 1.0.1
If you are in the shell already then simply sourcing the file will let you get what you want.
. filename.txt
echo $appid

How to put punctuation quotation in Awk command?

I am new to awk.I just try to write some thing that to exchange my text file.but I failed.
I want to output like 'hello'.
I used command awk '{print "'hello'"}' filename to do it.but failed:
output like: hello
but I used command awk '{print "\'hello\'"}' filename to do it.failed again:
output like: >
ok.it seems that the awk command do not get what I mean.
So I am confused about that .how to solve the problem.
guys thanks.
Using the ascii code:
awk '{print "\x27" "hello" "\x27"}' filename
Using a variable:
awk -v q="'" '{print q "hello" q}' filename
Example:
$ seq 2 > filename
$ awk '{print "\x27" "hello" "\x27"}' filename
'hello'
'hello'
$ awk -v q="'" '{print q "hello" q}' filename
'hello'
'hello'
Simply use double quotes:
awk "{print \"'hello'\"}" filename
Although that won't really modify your file.
awk '{print "'"'"'hello'"'"'"}' filename
clyfish's answer works, if you must have it output single quotes and you must use scripts that you pass on the command line.
What I usually do in cases like these, though, when I need to do quoting but I don't want to write a 'real' awk script, is this:
awk 'function q(word) { return "\"" word "\"" }
{ printf("mv %s SomeDir/;", q($0)) }'
What I've done is to define a function that returns whatever you pass it in double quotes. Then use printf to actually use it. Without doing that, I would have had to do:
awk '{ print("mv \"" $0 "\" SomeDir/;") }';
It gets pretty nasty. For more complicated examples, this can be a life saver.
However, suppose you really do need to output something with actual single quotes. In that case dealing with odd shell quoting rules while trying to pass scripts like this on the command line is going to drive you completely insane, so I would suggest you just write a simple throwaway file.
#!/usr/bin/awk
# hi.awk
{ print("'hello'") }
then call it:
awk -f ./hi.awk
You don't really even need the #! line in the file if you do it that way, but neither does it hurt.

AWK variable issue

The variable in awk does not return the result.
I am trying to get the next line of the matched value from file by using awk. It works fine without the variable. Thanks.
$ cat file
name=bobk
snm=sahh
emp=bklc
jdate=879
$
$ awk '/name/{getline; print}' file
snm=sahh ---------> Got the result
$
$ export MYVAR=name
$
$ echo $MYVAR
name
$
$ awk -v AVAR=${MYVAR} '/AVAR/{getline; print}' file
$ ---------> No result
You need to use the regexp match operator ~ against the whole line $0 as /AVAR/ is match for the string AVAR not the variable AVAR:
$ awk -v AVAR=${MYVAR} '$0~AVAR{getline; print}' file
snm=sahh
Using AWK variables to pass parameters is almost always cleaner as to intent; however, in this specific case, the resulting script is a bit more complex than it needs to be -- and breaking the rules a bit may actually be easier to understand and communicate to others.
With use of double-quotes to escape the script there is no need to use an additional AWK variable. That, and if we place the shell variable within /'s there is no need for the {}:
$ awk "/$MYVAR/ {getline; print}" file
snm=sahh
$

Resources