有没有办法使用多个通配符?

时间:2019-04-04 09:56:23

标签: makefile gnu-make

我尝试使用{em> GNU make 来组织Data Science CookieCutter project建议的研究数据,处理和可视化。我的原始数据的结构如下:

.
├── data
│   ├── interim
│   │   └── cleaned
│   └── raw
│       ├── ex01
│       └── ex02

我将实验1和2的数据分开存放,但在清洗后将它们合并。例如,data/raw/ex01/p0-c0.csv变成data/interim/cleaned/ex01-p0-c0.hdf

make 中,我使用了两个规则:

data/interim/cleaned/ex01-%.hdf: data/raw/ex01/source0/%.csv 
data/raw/ex01/source1/%.csv
  $(PYTHON) src/data/make_dataset.py $^ $@

data_interim_cleaned_ex01: $(addprefix $(CLEANED_DIR)/ex01-, $(addsuffix .hdf, $(basename $(basename $(notdir $(wildcard data/raw/ex01/source0/*.csv))))))

这使我感到很奇怪(特别是因为我复制了实验2的代码块),我的直觉告诉我,如果有多个(命名的)通配符,会更容易。我想正则表达式会有所帮助,但 make 中并不能(轻松)使用。

是否有解决此问题的规范方法?

2 个答案:

答案 0 :(得分:0)

以下解决方案并不是真正的规范make文件,但是恕我直言,make的许多规范功能实在太难理解和记住了。诸如“如何将我的文件名从形状X转换为Y”之类的问题一直出现,因为用户 do 使用目录和文件名结构作为组织项目的方式(一种非常自然和逻辑的方式)和make确实无法以编程方式处理此类任务。

一种方法是使用常用的命令行工具,例如sed,另一种是辅助程序库,例如gmtt,以分解字符串:

include gmtt-master/gmtt.mk

COMMON_ROOT = data/raw
COMMON_DEST = data/interim/cleaned

SOURCE = data/raw/ex01/p0-c0.csv data/raw/ex01/p1-c1.csv data/raw/ex02/p0-c0.csv data/raw/ex02/p1-c1.csv

# a pattern which separates a string into 5 parts (see below)
SEP_PATTERN = $(COMMON_ROOT)/ex*/*.csv

# use the elements (quoted variable-references '$$'!) in the new filename 
OUTPUT_PATTERN = $(COMMON_DEST)/ex$$2-$$4.hdf

# glob-match tests a glob pattern on a string and returns the string cut up at the border of 
# the glob elements (*,?,[] and verbatim strings). We immediately turn this into a gmtt table 
# by prepending the number of columns (5) to it:
SEPARATED = 5 $(foreach fname,$(SOURCE),$(call glob-match,$(fname),$(SEP_PATTERN)))

$(info $(SEPARATED))
$(info -----------------) 
$(info $(call map-tbl,$(SEPARATED),$(OUTPUT_PATTERN)$$(newline)))

输出:

$ make
5 data/raw/ex 01 / p0-c0 .csv data/raw/ex 01 / p1-c1 .csv data/raw/ex 02 / p0-c0 .csv data/raw/ex 02 / p1-c1 .csv
-----------------
data/interim/cleaned/ex01-p0-c0.hdf
data/interim/cleaned/ex01-p1-c1.hdf
data/interim/cleaned/ex02-p0-c0.hdf
data/interim/cleaned/ex02-p1-c1.hdf

make: *** Keine Ziele.  Schluss.

我担心将makefile变成动态生成规则的文件是不可避免的。

答案 1 :(得分:0)

答案也许不是您想要的,但是它不会在文件名中引入可变性或重复性。在添加或删除前缀(例如目录名)或后缀的词干名称之间,有简单或至少合理的方法来阐明Makefile之间的关系。其他任何事情都会带来麻烦,最终您将遭受折磨和复杂的转换规则或外部助手脚本来管理映射,或者,最糟糕的情况是,您只需要放弃make来进行依赖性管理。

一种解决方法是,您可以保留蛋糕也可以吃东西,这是在您首选的,人性化的命名约定与make管理的结构之间建立符号链接;但这充其量只是拐杖。

另一种可能对您有用的技术是touch一个简单的标志文件,以将一组复杂的依赖项标记为已处理。特别是如果某些依赖关系不能直接映射到另一个目标的一组输入文件名,则将所有依赖项放在一个简单的

后面
.input-files-done: some complex depencies
    touch $@

,然后仅依靠.input-files-done作为共享这些依赖性的目标,就可以简化Makefile和工作流程。

但是总而言之,我的主要建议是保持文件名统一,以便您始终可以使用简单的规则声明从一个文件名到另一个文件的显式依赖关系。