Awk field values inside make file - bash

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

Related

How to parse file to commands in bash

I'm trying to achieve some goal here and while I do know partials steps, I am not successful in putting it all together. I'm looking for an inline command for single usage on multiple hosts. Let's have SW repository file organized like this:
# comments
PROD_NAME:INSTALL_DIR:OPTIONS
PROD_NAME:INSTALL_DIR:OPTIONS
PROD_NAME:INSTALL_DIR:OPTIONS
Now, let's say we want to process the file and do some copy action on every one of the products. So, I can pipe grep getting rid of comment lines into while do cycle, where I use awk to break down each line to product name and it's path and complete it into copy commands. And that's too much of nesting for my skill level, I'm afraid. Anyone who'd care to share?
you can use a bash loop to do the same
$ while IFS=: read -r p i o;
do echo "cp $o $p $i";
done < <(grep -v '^#' file)
cp OPTIONS PROD_NAME INSTALL_DIR
cp OPTIONS PROD_NAME INSTALL_DIR
cp OPTIONS PROD_NAME INSTALL_DIR
remove echo to run as given.
Comments can be removed by
grep -v '^#'
For awk you have to specify the field delimiter:
awk -f: '{print $1, $2, $3}'
In order to craft copy commands you have to pipe the result to a shell.
echo -e '# comments\nNAME:DIR:OPT' |
grep -v '^#' |
awk -F: '{print "cp", $3, $2, $1}' |
sh
Even better: read a book.
Or this:
http://linuxcommand.org/learning_the_shell.php
https://en.wikibooks.org/wiki/Bourne_Shell_Scripting

How to do basename on second field in a file and replace it in line

I'm trying to get something like basename of second field in a file and replace it:
$ myfile=/var/lib/jenkins/myjob/myfile
$ sha512sum "$myfile" | tee myfile-checksum
$ cat myfile-checksum
deb32b1c7122fc750a6742765e0e54a821 /var/lib/jenkins/myjob/myfile
Desired output:
deb32b1c7122fc750a6742765e0e54a821 myfile
So people can easily do sha512sum -c myfile-checksum with no manual edits.
With sed or awk, that is how far i made it for now :)
awk -F/ '{print $NF}' myfile-checksum
sed -i "s|${value}|$(basename $value)|" myfile-checksum
Thanks.
You can set the field separators to both spaces and slashes and print the first and last fields:
awk -F" |/" '{print $1, $NF}'
With your input:
$ awk -F" |/" '{print $1, $NF}' <<< "deb32b1c7122fc750a6742765e0e54a821 /var/lib/jenkins/myjob/myfile"
deb32b1c7122fc750a6742765e0e54a821 myfile
In case your filename contain spaces, do remove everything from the first field up to the last slash, as indicated by Ed Morton:
$ awk '{hash=$1; gsub(/^.*\//,""); print hash, $0}' <<< "deb32b1c7122fc750a6742765e0e54a821 /var/lib/jenkins/myjob/myfile with spaces"
deb32b1c7122fc750a6742765e0e54a821 myfile with spaces
$ awk 'sub(".*/",$1" ")' <<< "deb32b1c7122fc750a6742765e0e54a821 /var/lib/jenkins/myjob/myfile"
deb32b1c7122fc750a6742765e0e54a821 myfile
The will work for any file name except one that contains newlines. If you have that case let us know.
sha512sum will simply use the file name you've passed to it - unchanged.
If you pass
sha512sum /path/to/file
it will give you:
123456.. /path/to/file
But if you:
pushd /path/to
sha512sum file
popd
it will give you
123456.. file
If the filename is a variable you can use parameter expansion like this:
pushd "${file%/*}"
sha256sum "${file##*/}"
popd
or even
# cd will not change the PWD of the current shell since
# the command runs in a sub shell
(cd "${file%/*}"; sha256sum "${file##*/}")
Having that $file contains the filename, ${file%/*} expands to the path without the filename and ${file##*/} expands to the filename without the path.

Bash grep variable as an expression

I have a problem with bash. I have big log file and I must check only a part of all log. In this purpose I use those expressions:
cat 29.log | grep -A 999 "15/02/06-22:30"
or
awk '$1>="15/02/06-22:30" {print$0}' 29.log
I want to change "15/02/06-22:30" at "date +%y/%m/d-%H:M" but when I use command
awk '$1>="date +%y/%m/d-%H:M" {print$0}' 29.log
or
awk '$1>='date +%y/%m/d-%H:M' {print$0}' 29.log
nothing happens.
Any ideas?
I need this in one command, not a script
You can pass shell variables to AWK using the -v flag:
awk -v d="$(date '+%y/%m/%d-%H:%M')" '$1>=d' 29.log
grep -A 999 `date '+%y/%m/d-%H:M'` 29.log

How to convert from command line to bash script?

I have a chain of commands that can execute all at once, however I wish to put it inside of a bash script. The problem is that I have no clue how to. My command is like so:
/usr/bin/sort -n db | /usr/bin/awk -F: '{print $1; print $2}' | db5.1_load -T -t hash newdb
How can I convert the above into a bash script?
This should normally be as simple as putting the shell command into a text file, and putting the Unix shebang on the first line of the file, which defines which program to use to run the script (in this case, /bin/bash). So this would look like:
#!/bin/bash
/usr/bin/sort -n db | /usr/bin/awk -F: '{print $1; print $2}' | db5.1_load -T -t hash newdb

dynamically setting a makefile variable using awk

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!

Resources