liberte@uiucdcsp.UUCP (01/10/85)
This csh trick has been puzzling me too long: Inside a command substitution, I want to do a variable substitution but not a filename expansion on the variable's value. I cant seem to get one without the other. For example: set x = "ls .*" set z = `echo $x` echo "$z" outputs: ls . .. .cshrc .login which is reasonable, but what I want is: ls .* You would think that using "$x" or $x:q instead of $x would do it: set z = `echo "$x"` Surprise. Same thing results. ---------------------------------- If we try: set x = "ls .*" set y = '"$x"' set z = `echo $y` echo $z # notice no '"'s we get: "$x" since the '"'s are quoted too. ---------------------------------- So let's try: set z = `eval echo $y` echo "$z" back to: ls . .. .cshrc .login ---------------------------------- Same thing with: set z = `eval echo " $x:q "` and set z = `echo " $x:q "` and set y = "echo $x:q" set z = `$y` ------------------------------------ I am out of creative ideas... mail and I'll post, Daniel LaLiberte University of Illinois, Urbana-Champaign usenet: ihnp4!uiucdcs!liberte arpanet: liberte@uiucdcs.Uiuc.ARPA
liberte@uiucdcs.UUCP (01/11/85)
/* Written 2:32 am Jan 10, 1985 by liberte@uiucdcsp in uiucdcs:net.unix */ /* ---------- "Csh substitution" ---------- */ Inside a command substitution, I want to do a variable substitution but not a filename expansion on the variable's value. I cant seem to get one without the other. For example: /* End of text from uiucdcs:net.unix */ Turns out there is a trivially easy solution. Just set noglob before the embedded command is executed to inhibit filename expansion. In this case it would work. But suppose you wanted some combination of filename expansion and no expansion within the same expression. Pretend you couldnt use noglob, just to make it interesting... Some of you may notice a problem using "'"s within "`"s. It seems that the characters after a "'" are forgotten. Dan ihnp4!uiucdcs!liberte liberte@uiucdcs.Uiuc.ARPA
liberte@uiucdcs.UUCP (01/30/85)
Here is a summary of solutions and other observations resulting from my recent query. My problem was how to inhibit filename expansion of a variable value inside of an embedded command. This is a more interesting problem than even I thought. There seem to be some misunderstandings as well as some possible bugs in csh that compounded the confusion. First the solutions. Of course, one solution I mentioned previously is to simply set noglob before the critical code. No double quotes (") are needed thereafter but they hold things together (set would try to set later items as variables). set noglob set x = "ls .*" set z = `echo $x` echo "$z" # The echo output here is not the goal. # The goal is to assign "ls .*" to z by way of # the embedded command. This is non-obvious only because the name "noglob" does not imply, in my mind, a filename expansion inhibitor. And how does "noglob" relate to the `glob` builtin command? A second, less obvious solution is to use double quotes around the embedded command in addition to double quoting the variable expansion inside the embedded command. To do this, you have to first assign the command string to a variable ($y) and use that value in the embedded command: set x = "ls .*" # filename expansion never occurs here. set y = 'echo "$x"' or set y = 'echo $x:q' set z = "`$y`" This does work. (The advantage of this method is that some variables may be expanded while others are not - within the same embedded command.) It is important to realize that the filename expansion IS, in fact, inhibited by quoting the variable within the embedded command, but then the RESULT of the embedded command is then filename expanded, unless it also is quoted. What follows are a few more interesting things that dont work. -------------------------- You cannot simply insert the command string with the quoted variable(s) into this "double quoted embedded command". The variable is expanded anyway because it is in double quotes no matter what other quotes it is in, and then the filename expansion is applied by the embedded command (I think). set z = "`echo $x:q`" # .* is expanded anyway or set z = "`echo "$x"`" # This is accepted - but it expands or set z = "`echo ""$x""`" # Same result or set z = "`echo """$x"""`" # Getting carried away. Unmatched `. or set z = "`echo \"$x\"`" # Unmatched `. or the suggestion from Ian! D. Allen below. One other method I discovered, but dont understand, requires three sets of quotes on the $x. Anything less and the .* is expanded: set z = "`echo "\$x:q"`" This doesnt work because it is too complicated. > From ihnp4!watmath!idallen Sun Jan 13 00:04:28 1985 > ... > The problem is the presence of special filename characters in the output > of the substitution. You might think you should try to quote them. You > might have thought you could echo quotes to protect the >>ls .*<< before > it was assigned to y: > > > set x = "ls .*" > > set y = `echo '"'"$x"'"'` > > You would think the output of the command substitution should be > >>"ls .*"<<, and indeed it almost is, but those quotes aren't going to > behave the way you expect. The contents of Y after the above is > >>"ls<<. No typo -- the first character is a quote and only the LS is > left. Why? Where did the filenames go? > > C Shell Funny #237: Quotes have no meaning in the output from variable > or command substitution. They behave just like ordinary characters. > {Unless they end up inside embedded commands - where they are then processed anew. - dan} > C Shell Corollary #237-A: Filename expansion is always done in the > output of variable or command substitution, because you can't use quotes > to protect the special characters. > {You can use quotes as I did.} > C Shell Funny #238: You get no error message if a filename expansion > in the output of a command substitution fails, that is, "No match" > never appears, unless the entire output of the substitution is null. > > You now know what happened. >>"ls .*"<< was the output of the > command substitution, but quotes aren't special, no file name > ended in a quote, so >>.*"<< expanded to nothing, leaving only >>"ls<<. > Since >>"ls<< isn't null, no error message appeared. > ... > I found all this nonsense hard to understand, so the Waterloo version > of the C Shell automatically "quotes" filename characters appearing in > the output of command substitution. My philosophy is -- since the > thing isn't being properly parsed (i.e. because quotes aren't doing > their job), it shouldn't be filename expanded either. > > To be consistent, I should also quote special characters in the output > of variable substitution, but I haven't had the courage to do it yet. > (Mabe I'll do it today...) > Thanks for everyones efforts. I have some other peculiar quoting phenomenon I may present later. If you come across something interesting, let me know. I would also like to create, or otherwise procure, a diagram of the parsing done by csh - at least history, jobnames (%n), aliases, variables, quotes (single, double, and command), and filename expansion. Send ideas. Daniel LaLiberte ihnp4!uiucdcs!liberte liberte@uiucdcs.Uiuc.ARPA U of Illinois, Urbana-Champaign, Dept of Computer Science (217) 333-8426