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

env_2_array

Discussion in 'Support' started by Peter Bratton, Jun 2, 2011.

  1. Peter Bratton

    Joined:
    Jul 1, 2008
    Messages:
    81
    Likes Received:
    0
    Is there a simple way to populate an array with the contents of the environment *without* using a file or the Windows clipboard for temporary storage?
    --
    Peter
     
  2. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,794
    Likes Received:
    29
    On Thu, 02 Jun 2011 20:07:46 -0400, Peter Bratton <> wrote:

    |Is there a simple way to populate an array with the contents of the environment *without* using a file or the Windows clipboard for temporary storage?

    Code:
    v:\> setarray env[50]
    
    v:\> echo %@execarray[env,set] > NUL
    
    v:\> do i=0 to 3 ( echo %env[%i] )
    ALLUSERSPROFILE=e:\Users\All Users
    APPDATA=e:\Users\vefatica\Application Data
    CommonProgramFiles=C:\Program Files\Common Files
    COMPUTERNAME=ZZ
    An _ENVSIZE variable would be useful.
     
  3. Peter Bratton

    Joined:
    Jul 1, 2008
    Messages:
    81
    Likes Received:
    0
    Thanks Vince. You're right, of course, but without _ENVSIZE, I have to use a file or CLIP: to determine the number of lines in my environment. I could over-estimate its length, but that's a workaround, not a solution.
    --
    Peter
     
  4. mathewsdw

    Joined:
    May 24, 2010
    Messages:
    855
    Likes Received:
    0
    It's not elegant, but it is quick enough to be used on my machine where I have 40 environment variables defined:
    Code:
    @Echo Off
    SetLocal
    SetArray env[50]
    Set Dummy=%@ExecArray[env,Set]
    Set I=0
    Do While "%env[%I]" != ""
       Set I=%@Inc[%I]
    EndDo
    Set I=%@Dec[%I]
    @Echo %I
    UnSetArray *
    EndLocal
    Quit 0
    
    
    I do think this is better than the alternatives you suggested.
     
  5. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,794
    Likes Received:
    29
    On Fri, 03 Jun 2011 17:05:55 -0400, Peter Bratton <> wrote:

    |---Quote (Originally by vefatica)---
    ||Is there a simple way to populate an array with the contents of the environment *without* using a file or the Windows clipboard for temporary storage?
    |
    |
    |Code:
    |---------
    |v:\> setarray env[50]
    |v:\> echo %@execarray[env,set] > NUL
    |---------
    |An _ENVSIZE variable would be useful.
    |---End Quote---
    |Thanks Vince. You're right, of course, but without _ENVSIZE, I have to use a file or CLIP: to determine the number of lines in my environment. I could over-estimate its length, but that's a workaround, not a solution.

    Here's another workaround.

    Code:
    v:\> set /a envsize=1 + %@execstr[set /x | echo %@lines[con]]
    42
    Even an internal/plugin _ENVSIZE would have to plow through the environment and
    count the strings.
     
  6. Peter Bratton

    Joined:
    Jul 1, 2008
    Messages:
    81
    Likes Received:
    0
    Agreed. It ain't pretty but it works just fine.
    --
    Peter
     
  7. Peter Bratton

    Joined:
    Jul 1, 2008
    Messages:
    81
    Likes Received:
    0
    Right again. This is more along the lines of what I was looking for, using memory for the grunt work. The downside is that the plowing lasts over 2 seconds when run from the command line, and in my case returns 41 the first time and 42 every subsequent instance in the same TCC session. Matthew's "not elegant" workaround returns 41 every time, and in a blistering 0.05 seconds, from a btm file.
    --
    Peter
     
  8. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    From: Peter Bratton
    | From: vefatica
    || v:\> set /a envsize=1 + %@execstr[set /x | echo %@lines[con]]
    ||
    || Even an internal/plugin _ENVSIZE would have to plow through the
    || environment and count the strings.
    |
    | Right again. This is more along the lines of what I was looking for,
    | using memory for the grunt work. The downside is that the plowing
    | lasts over 2 seconds when run from the command line, and in my case
    | returns 41 the first time and 42 every subsequent instance in the
    | same TCC session.

    That's because you add ENVSIZE to the list of variables the first time the command is completed (which is AFTER the calculation). You could modify it to:
    echo %@execstr[set /x | echo %@inc[%@lines[con]]]
    which does not define any new variables, hence provides the correct count each time.

    | Matthew's "not elegant" workaround returns 41 every
    | time, and in a blistering 0.05 seconds, from a btm file.

    NOTE: The internal variable _EXECARRAY is supposed to be set to the number of array elements the @EXECARRAY function loaded - in this case to the number of environment variables. (Beware! In the general case some elements may be set to empty strings.) If it were actually done, the count loop would not be needed... However, I just tested in both 12.01.44 and in 12.10.67, _EXECARRAY is not actually set at all.

    Code assuming _EXECARRAY is set correctly:
    setlocal
    setarray env[1000]
    set dummy=%@execarray[env,set]
    echo %_execarray environment variables are defined
    unsetarray env
    endlocal
    --
    Steve
     
  9. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,794
    Likes Received:
    29
    2 seconds! Wow!

    Anyway, I added _ENVSIZE to my 4UTILS plugin. New one at "ftp://lucky.syr.edu/4plugins/4utils.zip".
     
  10. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    From: vefatica
    | Anyway, I added _ENVSIZE to my 4UTILS plugin.

    Bad name! Implies total size of environment: names + values + terminators. Suggest _ENVCOUNT or _VARCOUNT.
    --
    Steve
     
  11. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,794
    Likes Received:
    29
    On Fri, 03 Jun 2011 20:53:27 -0400, Steve Fabian <> wrote:

    |From: vefatica
    || Anyway, I added _ENVSIZE to my 4UTILS plugin.
    |
    |Bad name! Implies total size of environment: names + values + terminators. Suggest _ENVCOUNT or _VARCOUNT.

    Shrewd observation. I changed it to _ENVCOUNT. New one in place.
     
  12. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,179
    Likes Received:
    11
    Couldn't you just use the index option of @execstr and accomplish the desired task? Why do you need a separate array?echo %@execstr[0,set /x]echo %@execstr[1,set /x]echo %@execstr[2,set /x]etc.or use a function:function env=`%@execstr[%1,set /x]`echo %@env[0]echo %@env[1]echo %@env[2]etc.-Scott-----vefatica <> wrote: ----->>||Is there a simple way to populate an array with the contents of the>environment *without* using a file or the Windows clipboard for>temporary storage?>>|>>|>>|Code:>>|--------->>|v:\> setarray env[50]>>|v:\> echo %@execarray[env,set] > NUL>>|--------->>|An _ENVSIZE variable would be useful.>>>>Here's another workaround.>>>>> Code:> v:\> set /a envsize=1 + %@execstr[set /x | echo %@lines[con]]>42>Even an internal/plugin _ENVSIZE would have to plow through the>environment and>>count the strings.
     
  13. Peter Bratton

    Joined:
    Jul 1, 2008
    Messages:
    81
    Likes Received:
    0
    The array is a whole lot faster, as the code snippet below demonstrates. The first loop is an adaptation of Matthew's approach, the second loop is yours.
    Code:
    timer
    setarray env[50]
    echo %@execarray[env,set /x] >& nul
    do i = 45 to 0 by -1
      echo %@format[2,%i] %@left[140,%env[%i]]
      if %i lt 45 .and. "%env[%i]" ne "" .and. "%env[%@inc[%i]]" eq "" echo ===========%=r%=n THE ENVIRONMENT CONTAINS %@inc[%i] VARIABLES %=r%=n============
    enddo
    unsetarray *
    timer off
    
    echo.
    
    timer
    do i = 45 to 0 by -1
      echo %@format[2,%i] %@left[140,%@execstr[%i,set /x]]
      if %i lt 45 .and.  "%@execstr[%i,set /x]" ne "" .and. "%@execstr[%@inc[%i],set /x]" eq "" echo ===========%=r%=n THE ENVIRONMENT CONTAINS %@inc[%i] VARIABLES %=r%=n============
    enddo
    timer off
    --
    Peter
     
  14. samintz

    samintz Scott Mintz

    Joined:
    May 20, 2008
    Messages:
    1,179
    Likes Received:
    11
    Your examples are kind of special case.
    The original comment was how to get the environment into an array
    not how to count the number of entries.

    IIRC, you did not want to use a file
    or the clipboard.
    This example gives you both the count
    and the environment loaded into an array.

    setarray env[1000]

    set _envcnt=%@execstr[set |! echo %@filearray[env,con]]

    The downside to the above is that _envcnt
    itself gets counted. You could instead use SET /V to add it to the
    volatile environment in which case it wouldn't get counted but you would
    need to to use SET /V to actually read its value too (e.g. %@execstr[set
    /v _envcnt]).

    -Scott

    Peter Bratton <> wrote
    on 06/05/2011 10:19:11 AM:


    and accomplish

    "%env[%@inc[%i]]" eq ""


    "" .and. "%@execstr[%

    ENVIRONMENT

     
  15. Steve Fabian

    Joined:
    May 20, 2008
    Messages:
    3,523
    Likes Received:
    4
    ---- Original Message ----
    From: samintz
    | setarray env[1000]
    |
    | set _envcnt=%@execstr[set |! echo %@filearray[env,con]]
    |
    | The downside to the above is that _envcnt itself gets counted.

    In all my experiments _envcnt is NOT included in the count, because it is created AFTER the SET is performed (inside @EXECSTR[]).

    I note your use of the "in-process pipe". In my tests it is substantially faster than the normal pipe for this application. I wonder if that is true generally.

    Of course, the new _ENVCOUNT internal variable in Vince's new 4utils.dll plugin makes the process unnecessary. If the documented TCC internal variable _EXECARRAY were actually created, the procedure below would make it even simpler:

    setarray env[1000]
    echo %@execarray[env,set] > NUL
    set _envcnt=%_execarray
    --
    Steve
     
  16. Peter Bratton

    Joined:
    Jul 1, 2008
    Messages:
    81
    Likes Received:
    0
    Guilty, I didn't clean it up before posting it.

    Hand-in-glove, an array can't be declared without specifying the number of elements.

    You recall correctly. I prefer to use memory over disk read/write on the assumption that it's faster. I could use the clipboard, but I have had clipboard contents changed by another app running simultaneously, so now I use the clipboard sparingly.

    I don't see that, the set command is run before _envcnt is filled, so its value is accurate. Although the memory reserved for the array is overstated, your example works.
    --
    Peter
     
  17. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,794
    Likes Received:
    29
    On Mon, 06 Jun 2011 12:17:23 -0400, Steve Fabian <> wrote:

    |Of course, the new _ENVCOUNT internal variable in Vince's new 4utils.dll plugin makes the process unnecessary.

    A user reported to me privately that in TCC/x64, "ECHO %_ENVCOUNT" causes a
    crash. Anyone else?
     
  18. vefatica

    Joined:
    May 20, 2008
    Messages:
    7,794
    Likes Received:
    29
    Never mind. Rex pointed out the error in my code. I'll upload a new one tonight.
     

Share This Page