开发者

How to use sed in a Makefile

I have tried putting the following in my Makefile:

@if [ $(DEMO) -eq 0 ]; then \
    cat sys.conf | sed -e "s#^public_demo[\s=].*$#public_demo=0#" >sys.conf.temp; \
else \
    cat sys.conf | sed -e "s#^public_demo[\s=].*$#public_demo=1#" >sys.conf.temp; \
fi

but when I run make, I get the following error:

sed: -e expression #1, char 30: unterminated `s' command

If I run the exact lines that contain sed in the console, they behave correctly.

Why a开发者_开发百科m I getting this error and how can the problem be fixed?


TL;DR: Use single quotes and use two $ signs. The expression is expanded twice, once by make and once by bash. The rest of this answer provides further context.

It might be the $ sign in the substitution that is interpreted by make as a variable. Try using two of them like .*$$#public_demo. Then make will expand that to a single $.

EDIT: This was only half the answer. As cristis answered: the other part is that one needs to use single quotes to prevent bash from expanding the $ sign too.


I suggest you use single quotes instead of double quotes, the $ might be processed as a special char by make before running sed:

cat sys.conf | sed -e 's#^public_demo[\s=].*$#public_demo=0#' >sys.conf.temp;


The make version in my machine is:

$ make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-redhat-linux-gnu

And the sed version:

$ sed --version
GNU sed version 4.2.1

I must add backslash for $ to prevent sed taking it as end of line:

cat sys.conf | sed -e 's#^public_demo[\s=].*\$$#public_demo=0#' >sys.conf.temp


Use something else than # to separate parts.


one problem I had with using sed in a makefile isn't addressed by the current answers, so I'll explain it here. I was populating Bash variables like so: remote_owner=$$($(MAKE) remote.owner) and then using those variables in my sed substitution. problem is, due to the convoluted way my rules are set up, remote_owner could have make's own output in it, giving me the error:

sed: -e expression #1, char 69: unknown option to `s'
make: *** [alter_table_local.sql] Error 1

for example, by adding debugging messages, I found local_owner set to:

make[1]: Entering directory `/home/jcomeau/rentacoder/jh'
jcomeau

the answer was to add the --silent option to make: remote_owner=$$($(MAKE) --silent remote.owner)


I tried double $$ sign but it didn't work in my problem, maybe $$$$ or $$$$$$$$ would have worked, because my Makefile calls other Makefiles and so on. But I found a better solution:

Create a shell file replacer.sh in the same folder as your Makefile that executes the sed command. Give it executable bit with

chmod +x replacer.sh

Now you can call this file in your Makefile:

./replacer.sh
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜