[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).