Announcement

Collapse
No announcement yet.

parsecount and command$()

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • parsecount and command$()

    While testing my app, I entered the following commandline in the IDE's Run/Command box:

    /g:2011-11-11 "E:\Test Code\test files\*.*" /b:-
    To get a count of the parameters, I coded:

    Code:
          CmdCount = Parsecount(Command$)
    This returns 1, where I was expecting 3. I don't understand why. I have read the help, and I don't see the problem.

    So I substituted the following loop to count parameters:
    Code:
          MaxParams = 5   
          For i = MaxParams To 1 Step -1 
             If Command$(i) = "" Then
                CmdCount = i -1  'could go to 0 if no params given...
             End If
          Next i
    There are no errors and CmdCount always comes out fine.

    So, I'm not stuck for a solution, but I am wondering what I'm misunderstanding about Parsecount. Can anyone explain why the count of those parameters came back as 1 and not 3?




    There's a second part to this topic:

    When I was coding the above loop, I was initially concerned that Command$(i) would cause an error when i is greater than the actual number of parameters.

    I'd never used TRY before, and I thought this was a good place for it. So I coded this test:

    Code:
          For i = MaxParams To 1 Step -1 
             Try
                x = Command$(i)
             Catch
                CmdCount = i -1  'could go to 0 if no params given...
             End Try
          next i
    but Command$(i) appears to be very forgiving and generates no runtime error.

    And since there was no error, the Catch is never triggered. (I always use #Dim All, and while debugging have tools on and debug error on - no errors detected.)



    It seems to me that there's something special about Command$() and so, (in addition to my question above about Parsecount), I was wondering if anyone can shed some light on these matters for me.

    Thanks!

  • #2
    John,

    From the help file (under "PARSECOUNT"):
    If string_delimiter is not specified, or contains an empty string, special rules apply. The delimiter is assumed to be a comma.
    Since you didn't specify a delimiter, a comma is assumed as delimiter, but your input string does not contain a comma, therefore the result of Parsecount is 1.

    Why don't you try this (using a space as the delimiter):
    CmdCount = Parsecount(Command$, " ")
    Kind regards
    Eddy

    Comment


    • #3
      Usually, I read pretty well, but today seems to be an exception! (Do you know how many times I read that and mentally visualized it as "spaces"???)

      So, I changed code to explicitly use:
      Code:
             CmdCount = ParseCount(Command$, " ")
      and it's now dividing the double-quoted string into separate parameters...

      ????

      Comment


      • #4
        Originally posted by John Montenigro View Post
        and it's now dividing the double-quoted string into separate parameters...
        Yes, because unfortunately the path name contains spaces ..
        One of the reasons I (still!) avoid the use of spaces in path- and filenames.

        Kind regards
        Eddy

        Comment


        • #5
          >and it's now dividing the double-quoted string into separate parameters...

          Of course it is: you specified SPACE as the delimiter. Space between "test" and "files" is still a space.

          I'm afraid you are just going to have to do this via brute strength. Regular expressions can be useful for this, as it can find things delimtied by quotes and word-breaks.

          For that matter, EXTRACT$ could be useful
          Code:
          ' Get everything up to but not including the first space or double quote
            Parm (first) = EXTRACT$(command_line), ANY  $SPC & $DQ)
          I'm sure you could loop on this.

          But INSTR might be easier here, as EXTRACT$ does not return the character which was actually used as the delimiter, and if there are multiple spaces delimiting two commands....
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            John,

            Here is kind of a quick-and-dirty'ish piece of code that handles spaces between double quotes.
            Using PB's powerful string functions I'm sure one could come up with atleast 10 other methods:

            Code:
            FUNCTION PBMAIN
                LOCAL sA, sB, sCh, sMarker AS STRING
                LOCAL i, j, lBetweenDQ AS LONG
                
                sMarker = CHR$(1)  'Use a non-ascii character
                    'String under test:
                sA = "/g:2011-11-11 "+ $DQ +"E:\Test Code\test files\*.*"+ $DQ +" /b:-"
                FOR i = 1 TO LEN(sA)
                    sCh = MID$(sA, i, 1)
            
                    SELECT CASE sCh
                        CASE $DQ  : lBetweenDQ = (lBetweenDQ = 0)
                        CASE $SPC : IF lBetweenDQ THEN MID$(sA, i, 1) = sMarker    
                    END SELECT
                NEXT i
            
                    'to remove double spaces
                DO WHILE INSTR(sA, $SPC + $SPC) 
                    REPLACE $SPC + $SPC WITH $SPC IN sA
                LOOP  
                
                i = PARSECOUNT(sA, $SPC)
                MSGBOX STR$(i)
                IF i > 0 THEN
                    FOR j = 1 TO i
                        sB = PARSE$(sA, $SPC, j)
                        IF INSTR(sB, sMarker) > 0 THEN REPLACE sMarker WITH $SPC IN sB
                        MSGBOX sB
                    NEXT j    
                END IF
            
            END FUNCTION
            Kind regards
            Last edited by Eddy Van Esch; 9 Mar 2009, 11:43 AM.
            Eddy

            Comment


            • #7
              Yes, I understand that it's now finding the spaces in the filespec. I was pointing out that it wasn't a working solution. (And no, I'm not going to try converting users to inserting commas between parameters on the commandline, when 30 years of commandline usage traditionally separates params with spaces, and 10 years of long filename usage traditionally treats double-quoted strings as one entity.)


              The Parsecount Help says:
              Fields may optionally be enclosed in quotes, and are ignored before the result string is returned.
              What does that mean "ignored"? Not counted? or that any delimiters within it are ignored? I may have mistakenly understood the second, when in fact it literally means the first???

              It continues:
              Any characters that appear between a quote mark and the next comma delimiter character are discarded. If no leading quote is found, any leading or trailing quotes are trimmed before the result string is returned.
              I took this to be explaining how Parsecount handles unbalanced DQs. Again, maybe I'm not seeing the full meaning here.


              Parsecount Help refers us to the help for PARSE$ for the full explanation, and there the help says:
              If delim$ is not specified or is null (zero-length), standard comma-delimited (optionally quoted) fields are presumed. In this case only, the following parsing rules apply. If a standard field is enclosed in optional quotes, they are removed. If any characters appear between a quoted field and the next comma delimiter, they are discarded. If no leading quote is found, any leading or trailing blank spaces are trimmed before the field is returned.
              Based on the first sentence, I'm understanding a "standard field" to be one that is comma-delimited. I take the second sentence to say that a comma-delimited quoted param will be treated as a unit, and be returned without its quotes. Characters that appear after a quote and before the next comma (or delimiter?) are discarded. Fine.

              Just out of curiosity, does the reference to "the next comma delimiter" pertain specifically as written, or does it mean "comma delimiter, or the delimiter you have specified" ??

              Perhaps I have been "reading into" the meaning, as I find it hard to believe that Parsecount does not treat a double-quoted string as a single entity.

              So how do I tell PARSECOUNT to respect the integrity of a DQ'd string, and still count params accurately? What syntax do I use for that?



              As for brute force methods, I think I've done that in the code posted in message #1, yes? Or did I miss something there, too?

              Here's another way that works:
              Code:
                    Dim cmd(1 To 10) As String
                    Parse Command$, cmd(), $Dq
                    i = 1
                    While Len(cmd(i))
                       MsgBox cmd(i),,"Param " & Str$(i)
                       Incr i
                    Wend
              BUT that will fail if the two non-quoted params are adjacent and separated by a space...

              But why the need for brute force, when all that's needed is for double-quoted strings to be handled as a single entity?


              Ah HA! An Insight! In my posted code in message #1 (where all is right in the world), I am relying on the implicit handling of COMMAND$() arguments BY THE IDE.


              This means there's a difference between how the PB IDE natively handles the commandline and how PARSECOUNT sees it. They don't work the same. And I think the IDE is doing the job right.

              Comment


              • #8
                Thanks for the code, Eddy. I'll have to step through it to understand, so I'll be awhile... But as you say, there are many ways to code such a function.

                But what good is Parsecount to me when it doesn't respect the integrity of a double quoted string, as a priority over the given or default delimiter?

                And yes, I DO see the value of Parsecount in reading lines from a file, and other such situations...

                as long as the data isn't double quoted...

                Comment


                • #9
                  But what good is Parsecount to me when it doesn't respect the integrity of a double quoted string, as a priority over the given or default delimiter?
                  As I read the doc, it DOES respect the integrity... IF you use the default delimiter of comma.

                  It sounds like you have a beef with history.... which decided to create COMMA-separated-values files instead of SPACE-separated-values files.... or maybe created SPACE-seperated command-lines instead of COMMA-separated command lines.

                  Bottom line I think: command-lines preceded long file names with spaces permitted and he who gets to the finish line first wins.
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Of couse looking at your command line, you have the explicit "/g:" and "/b:" options.... so why not go for TOTAL consistency and have a ....
                    Code:
                    /f:E:\Test Code\test files\*.*
                    option, too?
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      Right you are - since it looks like I have to do the parsing myself, I might as well be consistent and require an explicit switch for the filespec. Will complicate some other inputs, but overall, I come out ahead.

                      "As I read the doc, it DOES respect the integrity... IF you use the default delimiter of comma."
                      There's the rub. It just seems natural to me that if I change from the default comma delimiter to my own (even a $SPC), it will behave the same as the default comma (which handles double-quoted strings as one entity).

                      Comment


                      • #12
                        It just seems natural to me that if I change from the default comma delimiter to my own (even a $SPC), it will behave the same as the default comma (which handles double-quoted strings as one entity).
                        Sounds like a new feature sugggestion for PARSE, PARSECOUNT and PARSE$ ... which of course, can't be done if that delimiter is the $DQ, but you could qualify it somehow.

                        Until that happens, then, you have your choice of techniques... other than PARSE, PARSECOUNT or PARSE$, that is.
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13
                          Of course the easiest way in this case it to state that the file parameter must be the LAST parameter on the command line. Then you can extract the first two using EXTRACT$ on space delimiter, then take whatever is left, TRIM$ the $DQs and there you go.
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            I've just been through this exact problem myself.

                            I was writing a send-to utility. Windows packs up all the file names selected and returns them into the command$. Problem is, just as seen here, file names with no embedded spaces are passed plain, file names with embedded spaces are passed quoted.

                            Example command$:
                            c:\test\nospacefile.txt "c:\test\this name has spaces.txt"

                            My solution was to let PARSE break this on spaces into a string array. Start at the beginning, if the item has does not start and end with $DQ, add them and go to the next item.

                            If the item starts with $DQ but does not end with it, append a space and the next item in the array; then remove the next item from the array and repeat this step. Once the item starts and ends with $DQ, increment to the next item.

                            Repeat until null string found.

                            Then once again through the array to strip off all the $DQ's leaving you with a valid file list. Or for you, a valid parameter list.
                            The boy just ain't right.

                            Comment


                            • #15
                              >file names with embedded spaces are passed quoted

                              Hmm, afaik it should say: long filenames (and folders) are passed quoted
                              Not sure though.
                              hellobasic

                              Comment


                              • #16
                                Just my $0.02..... unless needing empty strings I would replace " " with Space$(1) just so its more obvious than "" or " " is when scouring code looking for whar in the warld that darn prog prb is....

                                Makes for easier reading and simplifies CNDS syndrome
                                Engineer's Motto: If it aint broke take it apart and fix it

                                "If at 1st you don't succeed... call it version 1.0"

                                "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                Comment


                                • #17
                                  Having been prodded by Michael to be consistent with the switch prefixes (and knowing that what I had was a tad ambiguous), I've revamped my Parse routine extensively. Now it's practically ironclad - nothing can get through that I don't know about explicitly. Also, I got rid of a handful of Globals and created a UDT for "CommandlineInfo" that holds all the status flags and values for the params found.

                                  A tough afternoon, but eminently satisfying!

                                  Cliff, good suggestion. I don't like that "whar in the warld" feeling, so I try to avoid " " and use $spc for that reason. Sometimes I forget, but not so much anymore.


                                  After reading Joseph's situation, I still would like to see Parsecount handle quoted strings as a unitary entity, even when I replace the default comma delimiter with one of my own...

                                  I'll be sending this in to PB's "Top 40 Request Line" tonight.
                                  Last edited by John Montenigro; 9 Mar 2009, 08:47 PM. Reason: Request sent to PB support!

                                  Comment


                                  • #18
                                    Hmm, afaik it should say: long filenames (and folders) are passed quoted
                                    Not sure though.
                                    Think about that a moment, Edwin: it's just not possible for the the compiler to handle it ...

                                    COMMAND$ is whatever was passed, with or without quotes; and COMMAND$ has no idea what is a file name and what is "just text." Unless you'd like the compiler to start putting quotes around whatever it thinks is a 'filename'

                                    Same with the PARSE family: it does not know what it is parsing is filenames; all it knows is, "here a string, here is the delimiter to use. "

                                    MCM
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment


                                    • #19
                                      COMMAND$ does not act like a variable, it acts like a function, hence, when asking it for a specific section of the command line, you get back that part. Quoting John's original command line:

                                      /g:2011-11-11 "E:\Test Code\test files\*.*" /b:-

                                      Paste that into the command line for the follow quick program:
                                      Code:
                                      #COMPILE EXE
                                      #DIM ALL
                                      
                                      FUNCTION PBMAIN () AS LONG
                                      LOCAL cIndex    AS LONG
                                      LOCAL tString   AS STRING
                                      
                                          DO
                                              tString = COMMAND$(cIndex)
                                              IF LEN(tString) = 0 THEN EXIT DO
                                              #DEBUG PRINT FORMAT$(cIndex) &"="& tString
                                              INCR cIndex
                                          LOOP
                                      
                                      
                                      END FUNCTION
                                      And when run (in the IDE in debug mode), will return this in the debug window:
                                      Code:
                                      Begin Debug at 7:36:06 PM on 3/9/2009
                                      0=/g:2011-11-11 "E:\Test Code\test files\*.*" /b:-
                                      1=/g:2011-11-11
                                      2=E:\Test Code\test files\*.*
                                      3=/b:-
                                      End Debug at 7:36:08 PM on 3/9/2009
                                      And is that not what is desired?
                                      Furcadia, an interesting online MMORPG in which you can create and program your own content.

                                      Comment


                                      • #20
                                        Note that I did point out that the IDE CORRECTLY parses an entry in the Run/Command pane... and yes, that is the behavior desired. Let's have the Parse family behave the same way the IDE parses the commandline: handling double-quoted strings as one entity, regardless of what's inside, and regardless of whether I'm using the default comma as my delimiter, or another character (including the $SPC)...

                                        Comment

                                        Working...
                                        X