env_2_array

#2
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.
 
Jul 1, 2008
81
0
71
Montreal
#3
|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.
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
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
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
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.
 
Jul 1, 2008
81
0
71
Montreal
#6
It's not elegant, but it is quick enough to be used on my machine where I have 40 environment variables defined:
Code:
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
I do think this is better than the alternatives you suggested.
Agreed. It ain't pretty but it works just fine.
--
Peter
 
Jul 1, 2008
81
0
71
Montreal
#7
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.
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
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
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.
2 seconds! Wow!

Anyway, I added _ENVSIZE to my 4UTILS plugin. New one at "ftp://lucky.syr.edu/4plugins/4utils.zip".
 
#11
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.
 

samintz

Scott Mintz
May 20, 2008
1,270
11
Solon, OH, USA
#12
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.
 
Jul 1, 2008
81
0
71
Montreal
#13
Couldn't you just use the index option of @execstr and accomplish the desired task? Why do you need a separate array?
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
 

samintz

Scott Mintz
May 20, 2008
1,270
11
Solon, OH, USA
#14
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:


> Quote:
>
> Originally Posted by samintz [image removed]
> Couldn't you just use the index option of @execstr
and accomplish

> the desired task? Why do you need a separate array?
>
> 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
 
#15
---- 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
 
Jul 1, 2008
81
0
71
Montreal
#16
Your examples are kind of special case.
Guilty, I didn't clean it up before posting it.

The original comment was how to get the environment into an array
not how to count the number of entries.
Hand-in-glove, an array can't be declared without specifying the number of elements.

IIRC, you did not want to use a file or the clipboard.
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.

This example gives you both the count and the environment loaded into an array.
Code:
setarray env[1000]      
set _envcnt=%@execstr[set |! echo %@filearray[env,con]]
The downside to the above is that _envcnt itself gets counted.
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
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
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?
Never mind. Rex pointed out the error in my code. I'll upload a new one tonight.