I have the following GNU makefile:
.PHONY a b c d
a: b c
b: d
c: d
d:
echo HI
I would like the target 'd' to be run twice -- since it is specified as a dependency by both b & c. Unfortunately, the target 'd' will be executed only once. The output of running make will simply be 'HI', instead of 'HI HI'.
How can I fix this?
Thanks!
To Clarify, the goal is something like this:
subdirs = a b c
build: x y
x: target=build
x: $(subdirs)
y: target=prepare
y: $(subdirs)
$(subdirs):
$(make) -f $#/makefile $(target)
build: x y
x: target=build
y: target=prepare
x y:
echo hi $(target) $#
touch $#
See also GNU Makefile rule generating a few targets from a single source file as it is an answer to a problem that is the opposite of this one.
Are you trying to do something like this:
.PHONY: a b c
define print-hi
#echo HI
endef
a: b c
b:
$(print-hi)
c:
$(print-hi)
Related
I am currently writing my first nextflow pipeline and I need to run different process in function of the parameter.
In fact, I would like, in one process, to select the channel where the input come from.
I've tested like that :
process foo{
input:
if(params.bar && params.bar2)
{
file reads from channel1.flatten()
}
else
{
file reads from channel_2.flatten()
}
output:
publishDir "$params.output_dir"
file "output_file" into channel_3
"""
my command line
"""
I obtain this error and I don't understand why.
No such variable: reads
Is there a way to do something like that ?
Thanks !
It's a bit of a weird error, but basically you just need to make sure your input declaration follows/matches the required syntax:
input:
<input qualifier> <input name> [from <source channel>] [attributes]
One solution might be to use the ternary operator to replace your if/else branch, for example:
ch1 = Channel.of( 'hello', 'world' )
ch2 = Channel.of( 1, 3, 5, 7, 9 )
params.foo = false
params.bar = false
process test {
echo true
input:
val myval from ( params.foo && params.bar ? ch1 : ch2 )
"""
echo -n "${myval}"
"""
}
Results:
$ nextflow run script.nf
N E X T F L O W ~ version 21.04.3
Launching `script.nf` [shrivelled_stone] - revision: 7b3f3a51df
executor > local (5)
[3b/fafa5e] process > test (2) [100%] 5 of 5 ✔
1
5
9
7
3
$ nextflow run script.nf --foo --bar
N E X T F L O W ~ version 21.04.3
Launching `script.nf` [irreverent_mahavira] - revision: 7b3f3a51df
executor > local (2)
[d2/09d418] process > test (1) [100%] 2 of 2 ✔
world
hello
Note that the new DSL 2 decouples the channel inputs from the process declaration, which might help to keep things readable, especially if the condition or action statements are more complex. For example:
nextflow.enable.dsl=2
params.foo = false
params.bar = false
process test {
echo true
input:
val myval
"""
echo -n "${myval}"
"""
}
workflow {
ch1 = Channel.of( 'hello', 'world' )
ch2 = Channel.of( 1, 3, 5, 7, 9 )
if( params.foo && params.bar ) {
test( ch1 )
} else {
test( ch2 )
}
}
Results:
$ nextflow run script.nf
N E X T F L O W ~ version 21.04.3
Launching `script.nf` [nauseous_pare] - revision: e1c4770ff1
executor > local (5)
[36/49d8da] process > test (4) [100%] 5 of 5 ✔
9
1
3
5
7
$ nextflow run script.nf --foo --bar
N E X T F L O W ~ version 21.04.3
Launching `script.nf` [goofy_euler] - revision: e1c4770ff1
executor > local (2)
[56/e635e8] process > test (2) [100%] 2 of 2 ✔
world
hello
I've a file like this
a b c,d
e f g
x y r,s,t
and I would like to split this into columns using "," as delimiter. The other columns should be copied.
Expected result :
a b c
a b d
e f g
x y r
x y s
x y t
Thank you
Using awk. Expects field separators to be space or tab:
$ awk '{
split($3,a,",") # split the third field on commas, hash to a
for(i in a) { # for all entries in a
sub(/[^ \t]+$/,a[i],$0) # replace last field with entries in a...
print # ... preserving separators, space or tab
}
}' file
a b c
a b d
e f g
x y r
x y s
x y t
Due to the use of sub() it will produce false results if there is a & in the $3. Also, as mentioned in the comments, using for(i in a) may result in records outputing in seemingly random order. If that is a problem, use:
$ awk '{
n=split($3,a,",") # store element count to n
for(i=1;i<=n;i++) { # iterate in order
sub(/[^ \t]+$/,a[i],$0)
print
}
}' file
For tab separated files:
$ awk '
BEGIN { OFS="\t" } # output field separator
{
n=split($3,a,",")
for(i=1;i<=n;i++) {
$3=a[i] # & friendly version
print
}
}' file
I need to auto-complete two parameters of a function, where the second parameter depends on the first one.
An example: the first parameter of a function "foo" can have values of "a" or "b". The second parameter can have values "10" or "11" in case the first parameter is "a", and "20" and "21" in case the first parameter is "b". So the following combinations of the parameters are legal:
foo a 10
foo a 11
foo b 20
foo b 21
The combinations are known upfront (they can be hardcoded).
The zsh completion system doc is quite obscure and the great How To didn't solve my problem neither. The closest would be to use _arguments, possibly with state action, but I didn't manage to make it work.
_arguments would make sense if you've got options mixed in with the arguments that you've described. Otherwise, just look in the $words array for the previous word - something like:
if (( CURRENT == 1 )); then
_wanted letters expl letter compadd a b
else
case $words[1] in
a) numbers=( 10 11 ) ;;
b) numbers=( 20 21 ) ;;
esac
_wanted numbers expl number compadd -a numbers
fi
I solved my case with the following:
IFS='
'
local -a options
_arguments "1:first:->first" "*:next:->next"
case "$state" in
first)
for o in $(_command_to_autocomplete_first); do
options+=("$o")
done
_describe 'values' options
;;
next)
for o in $(_command_to_complete_others $words[2]); do
options+=("$o")
done
_describe 'values' options
;;
esac
I am trying to run the following loop, the two while statements work, but the # c awk line seems to be causing me some problems.
printf "" >! loop.txt
# x = -125
while ($x <= -114)
# y = 32
while ($y <= 42)
# c =`awk '{ for ($1 = $x*; $2 = $y*){count[$1]++}}' text.txt`
printf "$x $y $c\n" >> loop.txt
# y++
end
# x++
end
With the awk line, I am trying to reference a file with lots of differing values in columns 1 and 2 of the text.txt file.
I want to be able to firstly reference all of the values in column 1 that start with $x (as they all have several decimal places), then reference from that sub-list all of the values in column 2 that begin with $y. After this second sub-list has been formed, I would like to count all of the entries valid to those conditions.
However, I keep getting syntax errors with the line, and I'm not sure that I'm using the correct function!
EDIT:
The executable file is a .csh type (C shell, I think)
A sample input format...
-125.025 32.058 2.25
-125.758 32.489 2.67
-125.349 32.921 3.49
-125.786 32.753 4.69
-125.086 33.008 2.78
And the expected output...
-125 32 4
-125 33 1
So this is all you want?
$ awk '{cnt[int($1)][int($2)]++} END{for (x in cnt) for (y in cnt[x]) print x, y, cnt[x][y]}' file
-125 32 4
-125 33 1
If you want to specify a range of x and y values, just add that range check before incrementing the array entry:
awk '
{ x=int($1); y=int($2) }
x>=-125 && x<=-114 && y>=32 && y<=42 { cnt[x][y]++ }
END { for (x in cnt) for (y in cnt[x]) print x, y, cnt[x][y] }
' file
I spit it into multiple lines to improve readability and added variables to avoid calling int() multiple times for each field.
Note that the above will read your input file just once compared to the script you posted in your question which will read the whole input file 132 times so you can imagine the performance improvement from that alone, never mind all the starting/stopping processes 132 times, etc.
The above use GNU awk for 2D arrays but can be easily simulated with other awks.
I have a list of products:
1, 2, 3, 4...
Which depends on a different list of sources:
z, y, x, w...
The dependence is one-to-one (the nth element of the first list has the nth element of the second list as its source), and the recipe is the same in all cases. There is, for all intents and purposes, no structure to the lists - it's not possible to write a simple expression which allows the nth element of the list to be generated from n. The solution that I know will work is
1 : z
[recipe]
2 : y
[identical recipe]
3 : x
[identical recipe]
4 : w
[identical recipe]
...but I don't like this because it makes it easier to make a mistake when modifying the lists or the recipe. I would prefer to take advantage of the correspondence pattern and begin with
SRCLIST = z y x w
DSTLIST = 1 2 3 4
And then somehow have a general rule like
DSTLIST_n : SRCLIST_n
[recipe]
Is there any way of doing something like this?
This is a bit ugly but I believe it should work. (There are probably slightly better ways but this was the first thing I came up with.)
SRCLIST = z y x w
DSTLIST = 1 2 3 4
# Create a list of : the length of SRCLIST
MIDLIST = $(foreach s,$(SRCLIST),:)
$(info SRCLIST:$(SRCLIST))
$(info DSTLIST:$(DSTLIST))
$(info MIDLIST:$(MIDLIST))
# Join the three lists together (in two passes since $(join) only takes two lists)
JOINLIST = $(join $(join $(DSTLIST),$(MIDLIST)),$(SRCLIST))
$(info joined:$(JOINLIST))
# eval each of the created strings to create the prerequisite entries
$(foreach r,$(JOINLIST),$(eval $r))
# Set the rules to build all the targets.
$(DSTLIST):
echo '$# for $^'
$ touch z y x w
$ make
SRCLIST:z y x w
DSTLIST:1 2 3 4
MIDLIST:: : : :
joined:1:z 2:y 3:x 4:w
echo '1 for z'
1 for z
echo '2 for y'
2 for y
echo '3 for x'
3 for x
echo '4 for w'
4 for w
I should note that this will not deal with spaces in any of the entries at all well (but that's generally true of make so nothing specific to this solution).
You could also always just create a Canned Recipe and then just stick that in each explicitly written out target as in your original idea.
Inspired by Etan, here is what I found worked:
SRCLIST = z y x w
DSTLIST = 1 2 3 4
# Make a list of ":" for combining
SEPARATOR = $(foreach s,$(SRCLIST),:)
# Define a parameterized rule which accepts the dst:src info as an argument
define dst-src
$1
[rule]
endef
# Define the list of dependencies
DST_SRC_RELNS = $(join $(join $(DSTCLIST),$(SEPARATOR)),$(SRCLIST))
# ^ DST_SRC_RELNS evaluates to z:1 y:2 x:3 w:4
# Print a preview of the rules the makefile generates itself
$(info $(foreach r,$(DST_SRC_RELNS),$(call dst-src,$r)))
# Generate the rules
$(foreach r,$(DST_SRC_RELNS),$(eval $(call dst-src,$r)))
I think that you could get away with not defining the parameterized rule dst-src by actually writing the rule out inside the $(eval ...), but I didn't like this for two reasons:
you need to define a newline macro for the result to be something that make will recognize as a rule
adding more text within the $(foreach ...) makes it even harder for a human reader to figure out what's really going on
Nice problem. You didn't mention which version of make you are using, but .SECONDEXPANSION often works well for these sorts of source lookup tables.
A sketch:
srcs := z x y w
targets := 1 2 3 4
.SECONDEXPANSION:
pairs := $(join ${targets},$(addprefix :,${srcs}))
lookup-src = $(patsubst $1:%,%,$(filter $1:%,${pairs}))
${targets}: $$(call lookup-src,$$#)
echo '[$^] -> [$#]'