1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Command line evaluation question - variable inside parenthesis

Discussion in 'Support' started by nikbackm, Nov 29, 2010.

  1. nikbackm

    Joined:
    May 30, 2008
    Messages:
    205
    Likes Received:
    1
    Hi,

    I stumbled upon a (to me) strange thing when I generated some SQL for piping to sqlite3.exe.

    These two statements where called in a loop:

    Code:
    set extraWhereCondParsed=%extraWhereCondParsed% OR (%thisCondParsed%)
    echo "%extraWhereCondParsed%"
    
    Two outputs from the echo command were:
    Code:
    "("Last Name" LIKE 'b*') OR (%thisCondParsed%)"
    "("Last Name" LIKE 'b*') OR (%thisCondParsed%) OR (%thisCondParsed%)"
    
    So the environment variable inside the parenthesis was not evaluated. (But other variables inside parenthesis elsewhere were evaluated, just not this one.

    Adding `` around the parenthesis:es fixed the problem.

    Code:
    set extraWhereCondParsed=%extraWhereCondParsed% OR `(`%thisCondParsed%`)`
    echo "%extraWhereCondParsed%"
    
    "("Last Name" LIKE 'b*') OR ("First Name" LIKE 'a*')"
    "("Last Name" LIKE 'b*') OR ("First Name" LIKE 'a*') OR ("First Name" LIKE 'a*')"
    
    Any idea what's going on? Would it always be a good idea (or even necessary in some cases) to use `` around literal (and not meant for e.g. command grouping) parenthesis:es?
     
  2. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    10,091
    Likes Received:
    85
    I cannot duplicate your results (I suspect you've simplified things in the message to the point that it doesn't show the complete steps to reproduce it).

    TCC will not expand variables inside a command group (this is a feature!), but with what you've shown TCC shouldn't think this *is* a command group.

    If you think you have a case where it is not expanding variables where it should please try to reduce it to a simple batch file.
     
  3. nikbackm

    Joined:
    May 30, 2008
    Messages:
    205
    Likes Received:
    1
    Here is a simplied batch to demonstrate the problem.

    Well, as simplified as I could make it with not too much effort. :)

    To trigger the (possible) error just run:
    Code:
    err bb -wfn.a* -wfn.b*
    
    Output "will" be:
    Code:
    extraWhereCondParsed: ("First Name" LIKE 'b*')
    extraWhereCondParsed: ("First Name" LIKE 'b*') OR (%thisCondParsed%)
    Active code page: 1252
    .header on
    .mode column
    .width 6 40 15 15 10 3 3
    SELECT Books."BookID","Title","Last Name","First Name","Date read","Owned","Bought Ebook" FROM Books
    INNER JOIN DatesRead USING(BookID)
            INNER JOIN AuthorBooks USING(BookID)
            INNER JOIN Authors USING(AuthorID)
    WHERE (Title LIKE '%%') AND (("First Name" LIKE 'b%%') OR ())
    ORDER BY "Last Name","First Name","Title";
    
    But it "should" be:
    Code:
    extraWhereCondParsed: ("First Name" LIKE 'b*')
    extraWhereCondParsed: ("First Name" LIKE 'b*') OR ("First Name" LIKE 'a*')
    Active code page: 1252
    .header on
    .mode column
    .width 6 40 15 15 10 3 3
    SELECT Books."BookID","Title","Last Name","First Name","Date read","Owned","Bought Ebook" FROM Books
    INNER JOIN DatesRead USING(BookID)
            INNER JOIN AuthorBooks USING(BookID)
            INNER JOIN Authors USING(AuthorID)
    WHERE (Title LIKE '%%') AND (("First Name" LIKE 'b%%') OR ("First Name" LIKE 'a%%'))
    ORDER BY "Last Name","First Name","Title";
    
    "First Name" LIKE 'a*' is simply not expanded from the variable.

    Error happens in routine :extractExtraWhereCond [whereCond].
    I added some "!!!" markers where it happens.

    I
     

    Attached Files:

    • err.btm
      File size:
      7.6 KB
      Views:
      4
  4. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    10,091
    Likes Received:
    85
    Re: Here is a simplied batch to demonstrate the problem.

    Not a bug.

    You're running into a problem with nested variable expansion -- your first argument is being expanded to "("First Name" Like 'b*')". TCC then looks to see if it should expand this argument again, and finds that it's now looking at a command group -- so it skips further expansion on the line.

    If you do a "setdos /x-4" it should work as you expect.
     
  5. nikbackm

    Joined:
    May 30, 2008
    Messages:
    205
    Likes Received:
    1
    Re: Here is a simplied batch to demonstrate the problem.

    Hm, I don't quite understand why the variable expansion would be nested.

    Code:
    iff defined extraWhereCondParsed then
        set extraWhereCondParsed=%extraWhereCondParsed% OR (%thisCondParsed%)
    else
        set extraWhereCondParsed=(%thisCondParsed%)
    endiff
    
    echo extraWhereCondParsed: %extraWhereCondParsed%
    
    The gosub routine is called two times.

    The first time the else branch is taken and extraWhereCondParsed is set to "(%thisCondParsed%)" The following echo also shows that "thisCondParsed" was expanded correctly and not "got stuck" inside extraWhereCondParsed.

    The next time the if-branch is taken, but this time the same "(%thisCondParsed%)" expression fails to expand. Is that just because it came after a preceding (not nested) variable expansion of "%extraWhereCondParsed%" on the same line?

    setdos /x-4 DID help, I just don't understand where the nesting comes in. Does it really matter (apparently) where in the line something is?

    Changing the order like this also makes it expand correctly.

    Code:
    iff defined extraWhereCondParsed then
        set extraWhereCondParsed=(%thisCondParsed%) OR %extraWhereCondParsed%
    else
        set extraWhereCondParsed=(%thisCondParsed%)
    endiff
    
    echo extraWhereCondParsed: %extraWhereCondParsed%
    
    I think I prefer using `` around the parenthesis since this expresses the intent best (assuming it's always guaranteed to disable what happens with command grouping here).
     
  6. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    10,091
    Likes Received:
    85
    Re: Here is a simplied batch to demonstrate the problem.

    *All* variable expansion is nested unless disabled with SETDOS /X-4. Every time a variable is expanded, the parser runs it through expansion again until it's sure there aren't any more variables. In your case, it expanded the variable, found a command group, and aborted further expansion on the entire command.
     
  7. nikbackm

    Joined:
    May 30, 2008
    Messages:
    205
    Likes Received:
    1
    Re: Here is a simplied batch to demonstrate the problem.

    Ok, I'm starting to get it. Must be a bit slow today. :)

    Thanks for taking the time to explain!


    So, the second gosub call, when

    Code:
    set extraWhereCondParsed=%extraWhereCondParsed% OR (%thisCondParsed%)
    
    is expanded, then "%extraWhereCondParsed%" will expand to a command group (as set by the else-branch the first call) and this will stop further expansion of variables on the same line. (Adding back quotes around "(" and ")" made them not behave like a command group so in that case it worked as wanted).

    Is this behavior documented? The topic "Command Parsing" - "3. Expanding variables" does mention that variable expansion works differently for some internal commands like IF and GLOBAL, but does not mention command groups.
    Or maybe that's implied by:
    Still don't understand how SETDOS /x-4 helped (as well) as that disables nested variable expansion. Which sounds like the opposite of what would be needed. And the variables WERE still expanded.
     
  8. nikbackm

    Joined:
    May 30, 2008
    Messages:
    205
    Likes Received:
    1
    Re: Here is a simplied batch to demonstrate the problem.

    Wait, think I just got it.

    Disabling nested variable expansion means that "the expander" just expands %extraWhereCondParsed% without further looking at the expanded value. So it does not see that it expands to a command group which would disable further variable expansions on the rest of the command line (and not only of the newly expanded value as setdos /X-4 does).

    Initially I just thought of disabling nested variable expansion as having to effect of not further expanding hidden variables becoming visible as a result of expanding an "outer" variable.

    Seems it can have other (more subtle) effects too! Well, at least I'm aware of this one now.
     

Share This Page