首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在文件列表中拆分成不同的行

如何在文件列表中拆分成不同的行
EN

Stack Overflow用户
提问于 2013-02-07 20:12:47
回答 4查看 4.7K关注 0票数 2

我有一个变量,其中包含用字符串_NEWLINE_分隔的文件列表。我需要将这个变量输出到一个文件中,这样每个文件都在一个单独的行中。诀窍是它需要在FreeBSD和Solaris上工作。

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

代码语言:javascript
运行
复制
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时,我得到了这样的信息(注意每一行末尾的$):

代码语言:javascript
运行
复制
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提出的解决方案,我创建了一个示例性的makefile,它提供了所需的结果,并且似乎正在开发FreeBSD和Solaris:

代码语言:javascript
运行
复制
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)
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-02-11 14:41:45

如果这是GNU make,那就全部在make中完成。

代码语言:javascript
运行
复制
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行中使用。如果你这样做:

代码语言:javascript
运行
复制
tgt:
    echo '${many-lines}'

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

代码语言:javascript
运行
复制
.ONESHELL:
tgt:
    echo '${many-lines}'

会以一种侵入性的方式起作用。正确的修复方法是确保${many-lines}的每一行都具有有效的sh语法。一些满嘴的,像:

代码语言:javascript
运行
复制
echolines = $(subst ${\n},'${\n}echo ',echo '${many-lines}')
.PHONY: aa
aa:
    $(call echolines,${many-lines})

天哪。

票数 1
EN

Stack Overflow用户

发布于 2013-02-08 00:01:28

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

真正的问题是跨平台的echo命令的实现不一致,而且默认情况下,make使用sh调用shell命令,这本身是相当不灵活的。

由于这个答案,我找到了一个更好的方法:"echo -e" when called directly and when called via a shell-script

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

\n (而不是_NEWLINE_ )构造字符串,将输出文件中的各个部分分成不同的行:

代码语言:javascript
运行
复制
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中简单地打印如下:

代码语言:javascript
运行
复制
@printf "$(some_string)" >> $(some_file)

同时工作在FreeBSD和Solaris上。

票数 1
EN

Stack Overflow用户

发布于 2013-02-07 20:29:26

声明:我没有使用Solaris或FreeBSD的经验.不管怎么说。

在make中,您可以使用$(patsubst模式、替换模式、文本)来替换模式。试试这个..。

代码语言:javascript
运行
复制
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))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14760124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档