2

我有一个变量,其中包含用 string 分隔的文件列表_NEWLINE_。我需要将该变量输出到一个文件中,以便每个文件位于单独的行中。诀窍是它需要在 FreeBSD 和 Solaris 上运行。

这就是我现在正在尝试的:

echo "lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf" | sed 's|_NEWLINE_|\'$'\n|g'

这适用于 FreeBSD 和 Solaris 上的 shell。但是当在 Solaris 上的 GNUmakefile 中运行时,我得到了这个(注意每行末尾的 $):

lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf$
lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src$
lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf$

如果我\'$'从 sed 中删除,那么它可以在 Solaris 上运行,但不能在 FreeBSD 上运行。也许有一种方法可以根据执行makefile的系统来告诉使用哪个版本?

编辑:感谢bobbogo 提出的解决方案,我创建了一个示例生成文件,它提供了所需的结果,并且似乎在 FreeBSD 和 Solaris 上都可以使用:

one-line := lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/\
priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/comm\
unity.conf: lib/alarms/priv/snmp_conf/community.conf

many-lines := { echo '$(subst _NEWLINE_,' && echo ',${one-line})'; }

.PHONY: all
all:
  $(shell $(many-lines) > test.txt)
4

4 回答 4

1

尝试了许多不同的解决方案,包括\n在这个答案中提到的定义:Add a newline in Makefile 'foreach' loop

真正的问题是跨平台的命令实现不一致,以及默认情况下使用 调用 shell 命令echo的事实,这本身是非常不灵活的。makesh

由于这个答案,我找到了一个更好的方法:直接调用和通过 shell 脚本调用时的“echo -e”

更好的方法是使用printf而不是echo

构造字符串,\n而不是_NEWLINE_分隔进入输出文件中单独行的部分:

some_string = lib/alarms-1.2/priv/snmp_conf/target_params.conf: lib/alarms/priv/snmp_conf/target_params.conf\nlib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf\n

然后在makefile中简单地打印它:

@printf "$(some_string)" >> $(some_file)

适用于 FreeBSD 和 Solaris。

于 2013-02-08T00:01:28.767 回答
1

如果这是 GNU make,那么一切都在 make 中完成。

one-line := lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf

define \n


endef

many-lines := $(subst _NEWLINE_,${\n},${one-line})

现在${many-lines}有你想要的。令人讨厌的是,它很难在 shell 行中使用。如果你这样做:

tgt:
    echo '${many-lines}'

make 将为每一行调用一个单独的shell 。第一次 shell 调用将得到一个未配对并退出并出现错误。'

.ONESHELL:
tgt:
    echo '${many-lines}'

将以一种侵入性的方式工作。正确的解决方法是确保每一行${many-lines}都有有效的 sh 语法。一些满嘴的像:

echolines = $(subst ${\n},'${\n}echo ',echo '${many-lines}')
.PHONY: aa
aa:
    $(call echolines,${many-lines})

嘘。

于 2013-02-11T14:41:45.017 回答
0

免责声明:我没有使用 Solaris 或 FreeBSD 的经验……无论如何。

在 make 中,您可以使用 $(patsubst pattern,replacement,text) 替换模式。试试这个...

FILENAMES := "lib/alarms-1.2/priv/snmp_conf/agent.conf: lib/alarms/priv/snmp_conf/agent.conf_NEWLINE_lib/alarms-1.2/priv/snmp_conf/agent.conf.src: lib/alarms/priv/snmp_conf/agent.conf.src_NEWLINE_lib/alarms-1.2/priv/snmp_conf/community.conf: lib/alarms/priv/snmp_conf/community.conf"

.PHONY: all

all:
    @echo $(patsubst _NEWLINE_,${\n},$(FILENAMES))
于 2013-02-07T20:29:26.790 回答
0

作为替代方案,我认为你的第一种方法会起作用,如果你只是加倍$“逃避”它:

sed 's|_NEWLINE_|\'$$'\n|g'
于 2013-02-08T02:29:30.000 回答