Правила создания шаблонов файлов с помощью регулярных выражений - PullRequest
0 голосов
/ 28 февраля 2019

Мне нужно преобразовать кучу файлов с такими именами:

bar_S4_R1_001.fastq.gz

bar_S4_R2_001.fastq.gz

В файлы с такими именами:

bar_R1_001.fastq.gz

bar_R2_001.fastq.gz

Я хотел бы сделать это с шаблоном Makefile ( docs , примеры )

У меня есть такой Makefile:

SHELL:=/bin/bash
files:
    touch foo_S13_R2_001.fastq.gz
    touch foo_S13_R1_001.fastq.gz
    touch bar_S4_R2_001.fastq.gz
    touch bar_S4_R1_001.fastq.gz
    touch baz_S9_R2_001.fastq.gz
    touch baz_S9_R1_001.fastq.gz

FILES:=$(shell find . -name "*.fastq.gz")
.PHONY: $(FILES)

demo: $(FILES)
$(FILES):
    @printf "source: $@ , target should be: " ; \
    echo "$@" | sed -e 's|\(_S[0-9]*\)\(_R[12]_001.fastq.gz\)$$|\2|'

пример:

$ make files
touch foo_S13_R2_001.fastq.gz
touch foo_S13_R1_001.fastq.gz
touch bar_S4_R2_001.fastq.gz
touch bar_S4_R1_001.fastq.gz
touch baz_S9_R2_001.fastq.gz
touch baz_S9_R1_001.fastq.gz

$ make demo
source: bar_S4_R1_001.fastq.gz , target should be: bar_R1_001.fastq.gz
source: foo_S13_R2_001.fastq.gz , target should be: foo_R2_001.fastq.gz
source: bar_S4_R2_001.fastq.gz , target should be: bar_R2_001.fastq.gz
source: baz_S9_R2_001.fastq.gz , target should be: baz_R2_001.fastq.gz
source: baz_S9_R1_001.fastq.gz , target should be: baz_R1_001.fastq.gz
source: foo_S13_R1_001.fastq.gz , target should be: foo_R1_001.fastq.gz

Очевидно, у меня есть мои "источник" и "цель"назад в рецепте «демо» здесь.Как я могу использовать шаблонное правило Makefile для этого вместо того, чтобы создать правильный файл?

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Первое решение - vanilla make:

PAT_START := _S
PAT_MID := 0 1 2 3 4 5 6 7 8 9
PAT_END := 0_ 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_ 9_

SUBSTITUTE := _

PAT12 := $(foreach c,$(PAT_START),$(addprefix $(c),$(PAT_END)))
PAT123 := $(foreach c,$(foreach c,$(PAT_START),$(addprefix $(c),$(PAT_MID))),$(addprefix $(c),$(PAT_END)))

$(info $(PAT12))
$(info $(PAT123))

FILES := foo_S13_R2_001.fastq.gz foo_S13_R1_001.fastq.gz bar_S4_R2_001.fastq.gz bar_S4_R1_001.fastq.gz baz_S9_R2_001.fastq.gz baz_S9_R1_001.fastq.gz

NEW_FILES := $(strip $(foreach f,$(FILES),$(foreach p,$(PAT12) $(PAT123),$(if $(subst $(subst $(p),,$(f)),,$(f)),$(subst $(p),$(SUBSTITUTE),$(f))))))

$(info $(FILES))
$(info $(NEW_FILES))

Второе использует gmtt , библиотеку GNUmake, которая значительно облегчает такие задачи:

include gmtt-master/gmtt-master/gmtt.mk

NEW_FILES := $(foreach f,$(FILES),$(call implode,$(call pick,1 4 5 6 7,$(call glob-match,$(f),*_S*_R[0-9]_*))))

$(info $(FILES))
$(info $(NEW_FILES))

Обратите внимание, что в решении gmtt используется glob , а не RE.

0 голосов
/ 28 февраля 2019

Сложно, но выполнимо с GNU, что делает благодаря (не) известной комбинации foreach-eval-call и функции замены и анализа строк :

SHELL         := /bin/bash
.DEFAULT_GOAL := all
FILES         := foo_S13_R2_001.fastq.gz foo_S13_R1_001.fastq.gz bar_S4_R2_001.fastq.gz bar_S4_R1_001.fastq.gz baz_S9_R2_001.fastq.gz baz_S9_R1_001.fastq.gz
TARGETS       :=

.PHONY: all

# $(1): name of the source file in X_Y_Z_T.fastq.gz form
# tmp: X Y Z T.fastq.gz
# tmp1: X
# tmp2: Y
# tmp3: Z
# tmp4: T.fastq.gz
define MYRULE
tmp  := $$(subst _, ,$(1))
tmp1 := $$(word 1,$$(tmp))
tmp2 := $$(word 2,$$(tmp))
tmp3 := $$(word 3,$$(tmp))
tmp4 := $$(word 4,$$(tmp))

$$(tmp1)_$$(tmp3)_$$(tmp4): $(1)
    @printf 'source: %s, target should be: %s\n' "$$<" "$$@"

TARGETS += $$(tmp1)_$$(tmp3)_$$(tmp4)
endef
$(foreach f,$(FILES),$(eval $(call MYRULE,$(f))))

all: $(TARGETS)

$(FILES):
    @touch $@

Демонстрация:

$ make
source: foo_S13_R2_001.fastq.gz, target should be: foo_R2_001.fastq.gz
source: foo_S13_R1_001.fastq.gz, target should be: foo_R1_001.fastq.gz
source: bar_S4_R2_001.fastq.gz, target should be: bar_R2_001.fastq.gz
source: bar_S4_R1_001.fastq.gz, target should be: bar_R1_001.fastq.gz
source: baz_S9_R2_001.fastq.gz, target should be: baz_R2_001.fastq.gz
source: baz_S9_R1_001.fastq.gz, target should be: baz_R1_001.fastq.gz

Примечание: двойное значение $$ в определении MYRULE является существенным, так же, как := назначение переменных (вместо = рекурсивных назначений).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...