How to concatenate variable in Makefile recipe - makefile

I get this Makefile:
LIST = foo bar
$(LIST):
echo $#
When I run make targets the outputs works as desired:
$ make foo
echo foo
foo
$ make bar
echo bar
bar
But if I concatenate a string another-, only another-foo works:
LIST = foo bar
another-$(LIST):
echo $#
$ make another-foo
echo another-foo
another-foo
$ make another-bar
make: *** No rule to make target 'another-bar'. Stop.
How can I concatenate a target to expand to all values in my variable?

The behavior you observe is standard: when writing
another-$(LIST)
make just replaces $(LIST) with its content, yielding another-foo bar.
That is, this has nothing to do with, e.g., a bash brace expression such as another-{foo,bar}.
Yet, you can achieve what you want by doing something like:
LIST = foo bar
$(addprefix another-,$(LIST)):
echo "$#"

Related

Extracting a substring from a variable in makefile

Basically, I have to match all targets of the form : "tests/mytests-runthis"
I have a rule that does this:
life-tests/%:
./(?????) < $#.in > runthis.tmp
-diff runthis.tmp $#.out
i need everything after the dash to go in the area "(?????)", so it would run
./runthis < mytests-runthis > runthis.tmp
How can I extract everything after the dash from what i would get from $#?
You can do this with patsubst:
$ cat Makefile
life-tests/%:
#./$(patsubst life-tests/%,%,$#).sh
$ cat hello.sh
#! /bin/bash
echo world
$ make life-tests/hello
world
The automatic variable $* expands to the string that matched the pattern (%):
life-tests/%:
./$* < $#.in > runthis.tmp
-diff runthis.tmp $#.out

How to use bash function with arguments in make file

I want to use the bash function in the make file. Without argument, it's working, but how I can use it with arguments.
all :
foo () { echo $1} ; foo "hello"
Writing bash code inside Makefile require special handling for all the characters that are special to Make. In particular, '$', which must be escaped (doubled). Also note that ';' is required before '}'.
In general, when writing bash/sh snipplet inside Makefile, ${XYZ} (or $(XYZ)) will refer to MAKE variable, and $$XYZ (or $${XYZ}}) will refer to the sh variable.
all:
foo() { echo $$1 ; } ; foo "hello"

How to use :put to append a variable at the end of the current line with vim

I have the following command, which I need to insert in a bash script:
vim file.txt -c ':let var=$foo' -c ':execute "normal! gg/string\<cr>V"' -c ":normal! d" -c ':execute "normal inewstring\<Esc>"' -c ':put =var'
What it does (or what I want it to do) is to use the variable foo, which is defined on the script, search for the first appearance of string select the whole line and delete it, then insert newstring and append the value of foo just after this new string. However, my code puts the value always in the next line, no matter if I change the x value in :[x]put.
As a novice in vim I'm not sure even if this way to achieve my goal is efficient, so any suggestion is welcome. Thanks in advance.
Let's say that we have this input file:
$ cat file.txt
blah
string foo
string foo
blah
What I'm expecting to obtain (defining $foo="hello") is:
$ cat file.txt
blah
newstringhello
string foo
blah
I am a big vim fan, but if I were you, I won't do it with vim.
Since you didn't post the example input the desired output, I can only guess what do you want from your description.
Given that we have:
kent$ cat f
blah
string foo bar
string foo bar
blah
And var="hello", the next sed one-liner changes the input file into:
kent$ sed "0,/string/{/string/s/.*/newString/};$ a \\$var" f
blah
newString
string foo bar
blah
hello
However I don't know if it is exactly what you wanted.
update
kent$ sed "0,/string/{/string/s/.*/newString$var/}" f
blah
newStringhello
string foo bar
blah

Can bash autocompletion span an equal sign

I'm wondering if it's possible to make autocompletion span an = sign. So, for example, I want to type foo BAR=[TAB][TAB], and have it fill in the possible values for BAR. I've tried the following: I have a file called 'bar', as follows:
#!/bin/bash
echo -e "BAR=100\nBAR=110\nBAR=200" | grep "^$2"
And then I do:
~> complete -C bar foo
If I type foo [TAB][TAB], it gives me some possible values for BAR. If, I type foo BAR=[TAB][TAB], it fails (it appends BAR=BAR= to the end of the command). (note, if I type bar 1 BAR=, it gives me a proper list of completions, so this is not an issue with the bar script).
This would be very useful for some scripts I have.
Create a function (in your .bashrc e.g.):
bar()
{
local POS=${COMP_WORDS[COMP_CWORD]}
if [ "${COMP_WORDS[1]}" = "BAR" ] && [ $COMP_CWORD -eq 3 ]; then
COMPREPLY=($(echo -e "100\n110\n200" | grep ^$POS ))
fi
}
and link function to command foo:
complete -F bar foo

How do I write one-liner script that inserts the contents of one file to another file?

Say I have file A, in middle of which have a tag string "#INSERT_HERE#". I want to put the whole content of file B to that position of file A. I tried using pipe to concatenate those contents, but I wonder if there is more advanced one-line script to handle it.
$ cat file
one
two
#INSERT_HERE#
three
four
$ cat file_to_insert
foo bar
bar foo
$ awk '/#INSERT_HERE#/{while((getline line<"file_to_insert")>0){ print line };next }1 ' file
one
two
foo bar
bar foo
three
four
cat file | while read line; do if [ "$line" = "#INSERT_HERE#" ]; then cat file_to_insert; else echo $line; fi; done
Use sed's r command:
$ cat foo
one
two
#INSERT_HERE#
three
four
$ cat bar
foo bar
bar foo
$ sed '/#INSERT_HERE#/{ r bar
> d
> }' foo
one
two
foo bar
bar foo
three
four

Resources