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

Why doesn't this work?

Discussion in 'Support' started by mathewsdw, Dec 20, 2012.

  1. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    First, batch file 1:
    Code:
    @Echo Off
    SetLocal
    @Echo %%*: %*
    @Echo %%#: %#
    @Echo _CMDLine: %_CMDLine
    Set Value="%@Field[1," ",%*]"
    Set I=1
    Do While %Value != ""
      @Echo "%%@Field[%I," ",*]: %Value
      Set /A I+=1
      Set Value="%@Field[%I," ",%*]"
    EndDo
    EndLocal
    
    and the results of running batch file 1:
    Code:
    [Z:\TCC Histories]VarRef1 a=b c=d e=f
    %*: a=b c=d e=f
    %#: 6
    _CMDLine: VarRef a
    "%@Field[1," ",*]: "a=b"
    "%@Field[2," ",*]: "c=d"
    "%@Field[3," ",*]: "e=f"
    
    Now batch file 2:
    Code:
    @Echo Off
    SetLocal
    @Echo %%*: %*
    @Echo %%#: %#
    @Echo _CMDLine: %_CMDLine
    Set Value=
    Set I=1
    Do While "%@Field[%I," ",%*]" != ""
      @Echo "%%@Field[%I," ",*]: "%@Field[1," ",%*]"
      Set /A I+=1
    EndDo
    EndLocal
    
    and the results of running it:
    Code:
    [Z:\TCC Histories]VarRef2 a=b c=d e=f
    %*: a=b c=d e=f
    %#: 6
    _CMDLine: VarRef2 a
    TCC: Z:\TCC Histories\VarRef2.btm [8]  Syntax error "@Field[%I,""
    Z:\TCC Histories\VarRef2.btm [8]  Usage : DO [n | FOREVER]
    TCC: Z:\TCC Histories\VarRef2.btm [13]  Unknown command "EndDo"
    
    The question is actually pretty simple: why doesn't batch file 2 run the same as batch file 1, which is what I would expect? After all, the only difference between the two batch files is that one tests a variable in the Do While whereas the other tests the @Field expression directly in The Do While. Why is that not allowed?

    Oh, just as another question, why does %_CMDLine only contain the first argument?
     
  2. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,520
    Likes Received:
    4
    Your primary issue is that you reversed the first and second parameters of @FIELD (which are the same as for @WORD) - first parameter is the quoted separator list, second is the field number desired. I stopped looking when I discovered this issue.
     
  3. rconn

    rconn Administrator
    Staff Member

    Joined:
    May 14, 2008
    Messages:
    10,091
    Likes Received:
    85
    %_cmdline is for key aliases; it will never return anything useful inside a batch file. You should be using %cmdline.
     
  4. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Steve, Ironically, you are correct but it doesn't matter. Here is the corrected version (and you can verify the corrections for yourself):
    Code:
    [Z:\TCC Histories]type VarRef2.btm
    @Echo Off
    SetLocal
    @Echo %%*: %*
    @Echo %%#: %#
    @Echo _CMDLine: %_CMDLine
    Set I=1
    Do While "%@Field[" ",%I,%*]" != ""
      @Echo "%%@Field[" ",%I,%*]: "%@Field[" ",%I,%*]"
      Set /A I+=1
    EndDo
    EndLocal
    
    And here are the results of executing it:
    Code:
    [Z:\TCC Histories]VarRef2 a b c d
    %*: a b c d
    %#: 4
    _CMDLine: VarRef2 a
    TCC: Z:\TCC Histories\VarRef2.btm [8]  Syntax error "@Field[""
    Z:\TCC Histories\VarRef2.btm [8]  Usage : DO [n | FOREVER]
    "%@Field[" ",1,*]: "b"
    TCC: Z:\TCC Histories\VarRef2.btm [11]  Unknown command "EndDo"
     
    [Z:\TCC Histories]
    
    Note that it manages to echo the second parameter!

    And even more ironically, the first batch file I originally showed (which was technically in error and you can verify that for yourself) runs fine!
    Code:
    [Z:\TCC Histories]type VarRef1.btm
    @Echo Off
    SetLocal
    @Echo %%*: %*
    @Echo %%#: %#
    @Echo _CMDLine: %_CMDLine
    Set Value="%@Field[1," ",%*]"
    Set I=1
    Do While %Value != ""
      @Echo "%%@Field[%I," ",*]: %Value
      Set /A I+=1
      Set Value="%@Field[%I," ",%*]"
    EndDo
    EndLocal
    
    Definitely wrong according to the documentation, but:
    Code:
    [Z:\TCC Histories]VarRef1 a b c d
    %*: a b c d
    %#: 4
    _CMDLine: VarRef1 a
    "%@Field[1," ",*]: "a"
    "%@Field[2," ",*]: "b"
    "%@Field[3," ",*]: "c"
    "%@Field[4," ",*]: "d"
     
    [Z:\TCC Histories]
    
    Definitely the correct output.

    Again, you were correct but it made absolutely no difference of any kind.

    And you didn't comment on why %_CMDLINE only shows the first argument.
     
  5. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    And Rex, you are, of course, correct, and I kind of suspected as much, but I couldn't find any reference to %cmdline in the documentation.
    And while we're on the subject of documentation, I couldn't find (or don't know how to search for) any references in the documentation to either %* or %# (and I know it at least was in there!). Given my often-mentioned bad memory, good documentation is essential for me, and while your documentation is very, very, good (about the best I've ever seen), it's still not perfect. (Although since it appears to be a limitation of the help engine that you can't search for "%" anything, "*", or "#". Maybe if you could suggest a keyword to search for that would take me there that would ease the problem considerably, and I'm more likely to remember a word than some semi-random punctuation.)
     
  6. vefatica

    Joined:
    May 20, 2008
    Messages:
    8,129
    Likes Received:
    33
    The help for CMDLINE is under "CMDLINE" but, of course, that doesn't help much if you don't know it exists.

    There is a page titled "System Variables" which discussed all (?) the non-_ variables. I don't think you can get to that page directly. You can get there via the "Topics Found" dialog (hate those things) that opens when you choose "Variables" or "System Variables" in the index.

    "%*" and "%#" are discussed under "Batch FileParameter", a rather logical place to look. Oddly, "Batch File Parameters" (plural) which seems even more logical takes you to the help for SHIFT. I don't like that.

    The index is my starting point for finding things in the help (old habit). If you start at the table of contents, things are a bit easier to find, but require more navigation.

    Typing "batch" on an empty command line and pressing F1 is pretty good, especially if the TOC is your default pane.
     
  7. Charles Dye

    Charles Dye Super Moderator
    Staff Member

    Joined:
    May 20, 2008
    Messages:
    3,374
    Likes Received:
    40
    HELP SYSVAR should do it.
     
  8. vefatica

    Joined:
    May 20, 2008
    Messages:
    8,129
    Likes Received:
    33
    That seems a bit like magic! That's the name of an HTM file? How would one know that?
     
  9. Charles Dye

    Charles Dye Super Moderator
    Staff Member

    Joined:
    May 20, 2008
    Messages:
    3,374
    Likes Received:
    40
    Find your page in the Table of Contents; left-click, then right-click on it and choose "Jump to URL..." The page name is in the top box, labelled "Current URL." If you can't see the whole thing, drag across it to scroll right. All we care about is the bit between the "::/" and the .HTM extension.

    Or, if you can find a link to it (there's a link to that particular page on the "Variables & Functions" page), you can just right-click on the link and choose "Properties" to see the page name.
     
  10. vefatica

    Joined:
    May 20, 2008
    Messages:
    8,129
    Likes Received:
    33
    Yes, I know. But none of that helps folks look stuff up unless they've been there, done that, and remember the file name.

    If you're in the help and want to go to something quite precise, say DIR, the index works best since you can just type DIR in the keywork box. The sad part is that that won't take you to the help for DIR; you must deal with a dialog offering a choice among DIR, PDIR, and DIRCMD (but I said DIR!). In contrast, PDIR in the keyword box leads to a dialog offering only DIR and PDIR. And more contrasting is that entering DIRCMD as keyword, you're taken directly to the DIRCMD help. I never liked those keyword dialogs popping up when I have entered something as precise as DIR (or ASSOC, ATTRIB, BEEP, CANCEL, CD (but not CDD), COPY, DO, [the list goes on]). Does anyone **ever** select something in the index **wanting** a dialog presenting related keywords?
     
  11. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,520
    Likes Received:
    4
    Firstly, VarRef2.btm must have an extra line (maybe a blank one?) before the DO, because the reported line numbers in the error messages do not match the listing. Secondly, the parser seems not to be DWIM when you have lots of quotation marks. the string "%@Field[1," ",%*]" has two quoted strings, 1) "%@Field[1," and 2) ",%*]" . When the string is on the right side of a variable assignment (Set Value="%@Field[1," ",%*]") the parser manages to interpret it as a quoted string which contains a quoted string, but not when the same construct is part of a conditional expression in DO WHILE.

    This is a batch file segment which performs what you tried correctly:
    do i = 1 to %#
    @Echo Field %I: "%@Field[" ",%I,%CMDLine]"
    EndDo
    Note the use of %# for loop limit, and %CMDLINE to represent the command line. BTW, it works properly even if one of the command line parameters is a quoted string with embedded spaces, e.g., "a b c".

    HTH, Steve
     
  12. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Steve, first off, you properly identified the problem and the only mystery here is why is this the first time I've ever run into this. Secondly, for whatever reason (and I really can't think of a good reason other than habit which probably reinforced by the fact that I have used many languages over the years, the only one of which actually provides an explicit count of the number of arguments being the TCC batch file language) I prefer to test for a null parameter to indicate end-of-list rather than using a count. And thirdly, there's a simple way (once I had realized on my own what the problem was) to "have my cake and eat it too" as the saying goes: Use a character other than a double quote to delimit the null string, and it can literally pretty much any character, for instance Do While B%@Field[" ",%I,%*]B != BB works just fine, although I tend to think that using single quotes would be more expected and therefore less confusing in this situation. (Somewhat ironically, back quotes (`) don't work here but I tend to believe that that's because they often have a "special" meaning to TCC.) And lastly as to my bias against using a specific variable for a count, in the "real" code a count isn't needed and therefore there isn't one, and I have a strong bias against creating variables that are really not needed and I tend to believe that that bias was one of the reasons I was known for "high-quality" code (if I do say so myself! ;)).

    And Steve, there was a line that I had accidentally retained from a previous (and somewhat different) version of the batch file that I had deleted when posting it without remembering to "fix up" the numbering. You must have really sharp eyes to have seen that!
     
  13. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    Steve, an update. I forgot myself why I'm not using %# in the original real-world application - it is completely unrelated to my needs. You, of course, are asking why. Well, as was thoroughly discussed earlier in this thread, I am using %CMDLINE to access the parameters passed to the batch file. You are, again, probably asking why. And the answer is simple, I like parameters that take the form /KE[YWORD][=[VALUE]], and TCC, like cmd.exe, turns "/ABC=DEF", one parameter, into two: "/ABC DEF", i.e. the equals sign is "eaten up" by the command line parser. (This behavior is due to Rex's desire to maintain complete upward compatibility with cmd.exe. While I do not disagree in the slightest with that decision, it is, unfortunately, maintaining compatibility with something that is often basically stupid - and this is oned of those "oftens".) Without going into a lot of unnecessary detail, this is completely unacceptable in terms of my needs. And when parsing the command line myself, the value of %#, of course, is completely and totally irrelevant.
     

Share This Page