OK, I think I now understand the problem FELIX-1471 is trying to solve. Sorry it's taken so long :-(
I have my own example that demonstrates it, just to confirm that I have the same understanding. > x = <echo aa; <echo ab; echo ac | grep -n a | tac>> aa 1 ab 3 ac IllegalArgumentException: Command not found: *:1 The return value of tac (and the value assigned to x) is " 1 ab 3 ac". The problem is that the <> used for grouping also evaluates the result, causing the exception. FELIX-1471 proposes using () for grouping and $() for evaluation. So the above example would become: > x = (echo aa; (echo ab; echo ac | grep -n a | tac)) and > installandstart = { <installbundle <$baseURI resolve $0>> start } would become: > installandstart = { $(installbundle $($baseURI resolve $0)) start } FWIW I still think it is possible to solve this without introducing $(), just by stopping <> at the start of a statement from evaluating: ka...@root> x = <echo aa; <echo ab; echo ac | grep -n a | tac>> aa 1 ab 3 ac ka...@root> <osgi:echo a b> a b ka...@root> <<osgi:echo a b>> a b ka...@root> <<bundle 0> tostring> org.apache.felix.framework [0] However, the $() approach works fine too and so I'm happy to support this, so we can get this issue resolved. I have tested the latest FELIX-1471.patch and it mostly works OK: > echo aa; (echo ab; echo ac | grep -n a | tac) aa 1 ab 3 ac but fails when the result of () is in an assignment: ka...@root> x = (echo aa; (echo ab; echo ac | grep -n a | tac)) org.osgi.framework.InvalidSyntaxException: expected value|substring at org.apache.felix.framework.FilterImpl.<init>(FilterImpl.java:81) at org.apache.felix.framework.Felix.getServiceReferences(Felix.java:2893) Derek 2009/8/18 Guillaume Nodet <gno...@gmail.com> > > On Tue, Aug 18, 2009 at 09:17, Derek Baum <derek.b...@paremus.com> wrote: > > > 2009/8/17 Guillaume Nodet <gno...@gmail.com> > > > > > > > > So in short, the patch does the following: > > > * replace <> with $() > > > * use ( ) for grouping commands when on the edge of the command > > > * make the number of evaluation predictable > > > * have a syntax and semantic which is mostly (fully) in sync with bash > > > * re-evaluate / split expanded arguments that are not quoted > > > > > > > > I can still see no reason for having () and $() as two separate operators. > > This unncessarily compllicates syntax without adding any new capability. > > > > You previously gave the following example to demonstrate the need for a > > separate grouping operator: > > > > >The grouping operator is imho needed to be able to order pipes and > > columns: > > > (echo a ; echo b) | tac > > > echo a ; (echo b | tac) > > > > However, this example works fine with the existing <> execution quotes: > > > > ka...@root> <echo a; echo b> | tac > > ab > > ka...@root> echo a; <echo b | tac> > > a > > b > > > > Do you have any other example or use case that demonstrates the need for a > > separate grouping operator? > > > > () in bash is NOT only used for grouping - it executes the command within > > (), just like the existing <>. > > $() in bash executes and captures stdout into a string - equivalent to > > <command args | tac> in gogo. > > > > Well the key difference between those operators in bash is the number of > times the evaluation happen. > > ( ) does not change the number of times a command will be evaluated, that's > why i call it grouping. > What i mean is that if you remove the ( ), the commands will be executed the > same number of time. > echo a => echo a > ( echo a ) => echo a > ( ( echo a ) ) => echo a > All of those will produce the same result. > > $( ) will increment the number of evaluation each time it's used, and is > therefore not idemptotent. > echo echo echo a => echo echo a > $(echo echo echo a) => echo a > $( $( echo echo echo a) ) => a > > I don't really see how we can conflate both operators using < > or any other > syntax. > With the current state of gogo, you're not really sure how many times > evaluation will happen. > > > > > > To try to understand the need for separate () and $() operators, I have > > taken the gogo TestParser.java from the FELIX-1471.patch and replaced both > > $() and () with <>. I then ran the test against the unpatched code. > > > > All tests worked except some newly added tests within > > testGroupingAndEvaluation() like: > > > > assertEquals("a", c.execute("<echo echo a>") + ""); > > > > This fails because <echo echo a> evaluates to the String "echo a", which is > > then evaluated as a command and the command 'echo a' is not found. > > > > assertEquals("a", c.execute("$(echo echo a)") + ""); > > > > This works because of the complex re-parsing done by $() that you describe > > below. > > > Right, and I think this reparsing of arguments should be done anyway. So > maybe we need a separate jira for that one. > > I think I understood where our uncomprehension comes from. I first started > to have a look at FELIX-1325 (throwing an exception when the can't be found, > even if it has no arguments). The problem is that all those issues are > linked. > What you describe above works only because when you have a single token on > the command line and that no command is found, the token is simply returned. > This means that in all the above examples, the number of evaluation is not > really important, because executing "a" will return "a". > This hides some real issues imho, as the following tests, that all pass on > trunk show: > > assertEquals("echo echo", c.execute("echo echo echo")); > assertEquals("echo", c.execute("<echo echo echo>")); > assertEquals("", c.execute("<<echo echo echo>>")); > > assertEquals("echo a", c.execute("echo echo a")); > assertEquals("a", c.execute("<echo echo a>")); > assertEquals("a", c.execute("<<echo echo a>>")); > > > So the behavior of < > is that it run the command(s) inside it *and* > evaluates it. It's not only grouping. > > Now, let's take an example: > > assertEquals("a", c.execute("echoout \"a\nb\" | grep a | capture")); > assertEquals("b", c.execute("echoout \"a\nb\" | grep b | capture")); > assertEquals("ab", c.execute("<echoout \"a\nb\" | grep a | capture> > ; <echoout \"a\nb\" | grep b | capture> | capture")); > > assertEquals("", c.execute("<echoout \"echo\ngrep\" | grep echo | > capture> ; <echoout \"echo\ngrep\" | grep grep | capture> | capture")); > > The first two tests are ok. The third test is equivalent to "test1 ; test2 > | capture". > Remember that atm ';' takes precedence over '|'. > > Now the last test is the same as the third one, but with different values. > The output should be "echogrep", but isn't, due to the additional > evaluation. > The third test would also fail if we apply FELIX-1325 afaik. > > > > > > In bash, if you need to re-parse some text, you use the 'eval' command: > > > > $ eval $(echo echo '$HOME') > > /Users/derek > > > > We could take exactly the same approach in gogo, by adding a simple eval > > command for use on the rare occassions when it is required. > > > > Derek > > > > > > > > > > > > > > > I'm happy to discuss things further, but the major problem is related to > > > make the evaluation predictable, which sounds easy, but is not really ... > > > And this require to re-evaluate / split the expanded arguments. > > > See the following example: > > > assertEquals("a", c.execute("$($(echo echo echo a)) | capture")); > > > The "echo echo echo a" command is executed and prints "echo echo a". This > > > result is inside $() so it has to be interpreted as a full command line, > > > not > > > as a single argument which would be a string "echo echo a" as this would > > > return a command not found. > > > > > > > > > > > > -- > Cheers, > Guillaume Nodet > ------------------------ > Blog: http://gnodet.blogspot.com/ > ------------------------ > Open Source SOA > http://fusesource.com