bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: awk or sed


From: Greg Wooledge
Subject: Re: awk or sed
Date: Mon, 25 Apr 2011 08:41:15 -0400
User-agent: Mutt/1.4.2.3i

On Sat, Apr 23, 2011 at 11:07:06AM +0430, ali hagigat wrote:
> I have a makefile and I want to print each word of the variable, .VARIABLES
> on a separate line.

> It seems that the previous simple solution of Mr. Johnson here does not
> work, means: printf "%s\n" $var

make(1) is a separate program from bash.  The printf solution would
work with a *bash* variable:

imadev:~$ var='D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ...'
imadev:~$ printf '%s\n' $var
D
?F
CCACHE_DIR
DESKTOP_SESSION
CWEAVE
?D
GTK_RC_FILES
@D
...

(Technically you'd need to do a 'set -f' first, to avoid globbing of
the individual words.  E.g. if I had happened to have a file named IF
in my directory, the word ?F would have been expanded out to match the
filename(s).  I omitted that for simplicity, but you can't omit it in
real life.)

> This is the content of .VARIABLES:
> 
> .VARIABLES=<D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D
> XAUTHORITY GDMSESSION XMODIFIERS CURDIR SHELL RM GDM_LANG _ PREPROCESS.F
> var2 LINK.o OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST @F HISTCONTROL USERNAME
> ...........................
> It was long and I did not copy the rest of the lines.

Now you've gone and changed the question.  You're asking a question
about make(1) on the bash bug mailing list.  Specifically, you're asking
a question about make(1) *and assuming that it is the same as asking a
question about bash*, and that is (I believe) the primary source of
your confusion.

Makefiles use a separate syntax, have a separate variable space, have
an entirely separate *purpose*, and therefore separate semantics
associated with their lines.  Lines of a bash program are commands
that are executed in sequence.  Bash is a procedural language.  Lines
of a Makefile are not commands; they are definitions.  In a Makefile,
you define variables that can be used by rules, and then you define
rules that tell make(1) what to do with file X to produce file Y.
Makefiles are therefore closer to a functional language than a procedural
language.

Now, you're probably even more confused, because you aren't focused on
the overall structure of the language; you're just focused on one little
tiny part of one rule, which happens to be something that gets passed to
a shell (typically /bin/sh, not bash) after processing.  The "after
processing" part is key here.  make(1) does its *own* processing of the
line from the rule, before passing the result to the shell.  This is
because make(1) has its own variables, and it expands those before
passing the command to the shell -- then the shell has *its* own set of
variables, which may or may not be relevant, depending on the command
in question.

So.  You have a Makefile, and in it you have some variable defined
(I don't actually know what the period at the start of the make(1)
variable name means, so I'll assume it's not relevant at this time).
Then you want to write a rule which somehow uses this variable; and
you want this variable to be passed to a shell, and then you want the
shell to take that variable and write it on standard output, one word
per line.  Right?  Right.  Let me brush off my 15-year-old knowledge of
Makefiles and see if I can hack this together....

OK, here's the first try, using the most naive approach:

imadev:~/tmp$ cat Makefile
.VARIABLES=<D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ...>

default:
        printf '%s\n' $(.VARIABLES)

But this doesn't work:

imadev:~/tmp$ make
printf '%s\n' <D ?F CWEAVE ?D @D @F CURDIR SHELL RM CO TZ _ PREPROCESS.F 
ftp_proxy LINK.o OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST LINK.p CC COMPILE.f 
NETHACKOPTIONS CHECKOUT,v CPP LINK.cc P4CLIENT PATH LYNX_CFG LD TEXI2DVI 
FVWM_USERDIR YACC COMPILE.mod ARFLAGS LINK.r WINDOWID FVWM_MODULEDIR LINT.c 
LINT YACC.y AR .FEATURES TANGLE LPDEST GET %F DISPLAY COMPILE.F no_proxy 
CTANGLE VISUAL .LIBPATTERNS LINK.C PWD LINK.S PREPROCESS.r PKG_CONFIG_PATH 
LINK.c MANPATH LINK.s HOME LOGNAME ^D LC_TIME COLORTERM MAKE SHLVL AS 
PREPROCESS.S ERASE COMPILE.p MAKE_VERSION EDITOR FC HOSTDISPLAY .DEFAULT_GOAL 
LESS %D WEAVE MAKE_COMMAND LINK.cpp F77 OLDPWD .VARIABLES PC *F COMPILE.def LEX 
MAKEFLAGS MFLAGS *D EMAIL LPHOSTS LEX.l SLAB_PATH +D COMPILE.r +F M2C COLORFGBG 
MAKEFILES COMPILE.cc <F CXX COFLAGS PAGER COMPILE.C ^F COMPILE.S LINK.F 
SUFFIXES COMPILE.c COMPILE.s .INCLUDE_DIRS MAKELEVEL MAKEINFO http_proxy TEX 
LANG TERM F77FLAGS LINK.f
/bin/sh: D: cannot open
make: *** [default] Error 1

OK, this is informative.  Do **NOT** ignore an error message.  Learn from
it.  We can see that /bin/sh tried to open "D".  This is obviously because
it interpreted the <D as a redirection, rather than an argument for the
printf command.  So, we're making progress!  We just need to get the
make(1) variable into an actual shell variable, and then let the shell
expand it.

imadev:~/tmp$ cat Makefile
.VARIABLES=<D ?F CCACHE_DIR DESKTOP_SESSION CWEAVE ?D GTK_RC_FILES @D ...>

default:
        v='$(.VARIABLES)'; printf '%s\n' $$v

(Note that this would fail if .VARIABLES contained any single quotes
of its own; we'll just use this simple-but-dangerous form for now.)
And then:

imadev:~/tmp$ make
v='<D ?F CWEAVE ?D @D @F CURDIR SHELL RM CO TZ _ PREPROCESS.F ftp_proxy LINK.o 
OUTPUT_OPTION COMPILE.cpp MAKEFILE_LIST LINK.p CC COMPILE.f NETHACKOPTIONS 
CHECKOUT,v CPP LINK.cc P4CLIENT PATH LYNX_CFG LD TEXI2DVI FVWM_USERDIR YACC 
COMPILE.mod ARFLAGS LINK.r WINDOWID FVWM_MODULEDIR LINT.c LINT YACC.y AR 
.FEATURES TANGLE LPDEST GET %F DISPLAY COMPILE.F no_proxy CTANGLE VISUAL 
.LIBPATTERNS LINK.C PWD LINK.S PREPROCESS.r PKG_CONFIG_PATH LINK.c MANPATH 
LINK.s HOME LOGNAME ^D LC_TIME COLORTERM MAKE SHLVL AS PREPROCESS.S ERASE 
COMPILE.p MAKE_VERSION EDITOR FC HOSTDISPLAY .DEFAULT_GOAL LESS %D WEAVE 
MAKE_COMMAND LINK.cpp F77 OLDPWD .VARIABLES PC *F COMPILE.def LEX MAKEFLAGS 
MFLAGS *D EMAIL LPHOSTS LEX.l SLAB_PATH +D COMPILE.r +F M2C COLORFGBG MAKEFILES 
COMPILE.cc <F CXX COFLAGS PAGER COMPILE.C ^F COMPILE.S LINK.F SUFFIXES 
COMPILE.c COMPILE.s .INCLUDE_DIRS MAKELEVEL MAKEINFO http_proxy TEX LANG TERM 
F77FLAGS LINK.f'; printf '%s\n' $v
<D
?F
CWEAVE
?D
@D
@F
CURDIR
SHELL
RM
CO
TZ
_
PREPROCESS.F
ftp_proxy
LINK.o
OUTPUT_OPTION
COMPILE.cpp
MAKEFILE_LIST
LINK.p
CC
COMPILE.f
NETHACKOPTIONS
CHECKOUT,v
CPP
LINK.cc
P4CLIENT
PATH
LYNX_CFG
LD
TEXI2DVI
FVWM_USERDIR
YACC
COMPILE.mod
ARFLAGS
LINK.r
WINDOWID
FVWM_MODULEDIR
LINT.c
LINT
YACC.y
AR
.FEATURES
TANGLE
LPDEST
GET
%F
DISPLAY
...

I stopped pasting here and added the "..." myself.  The output goes on
for quite some time.  Why?  Hell if I know.  Some make(1) thing I
assume.  Presumably one of those weird <D or ?D or @D things in your
make(1) variable definition meant something to make(1) and was
expanded in some way.  Maybe that's even what you wanted.  I really
don't know, nor do I care at this point.

If you have any further questions about bash, feel free to ask them
here.  But if your questions are really about make(1), you'll have to
find some place that supports make(1).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]