6th edition by Eric Pement
<pemente@northpark.edu>
27 Dec. 2002 (major overhaul)
Given: Your operating system is MS-DOS or Windows (3.x, 9x, ME, WinNT,
Win2K, etc.), and
Given: Your task is to put strings into environment variables. Those
strings might be:
How do you get those strings from the keyboard/screen/diskfile, and put them into an environment variable where you can manipulate them further? This is the subject of this paper.
For the first time, this sixth edition divides the answer into multiple parts. Two answers are just for users of Windows 2000 or Windows NT, and two answers are for users of MS-DOS and other flavors of Windows.
The solutions will be listed in order of ease-of-use (my personal opinion). When I want answers and I have to choose between multiple solutions, I want the easiest and simplest to use right at the top. So, that's the way I've written this file for you. If you find any problems or mistakes, please let me know so I can fix it for the next edition.
Choose your operating system and command processor:
My personal favorite solutions are to use 4DOS or 4NT, because they make handling environment variables a breeze. The solutions with these utilities are short, direct, and well-documented. I think that 4DOS or 4NT, both from www.jpsoft.com, are an investment well worth the purchase price for any long-term computer user. Their product has deservedly won awards for many years.
However, since many computer users cannot install 4DOS/4NT or expect it to be installed on several target machines in a school or business firm, I have remove the 4DOS/4NT solutions to separate files.
I list the solutions in order of ease-of-use (my subjective opinion). My personal favorite is #1, since I'm a licensed user of 4DOS. If I couldn't use 4DOS, my next choice would be #2, an external utility dedicated to this task. I list sed and awk as a separate solution (#3), even though they are also "external utilities", simply because I know a lot about them and because they are extremely safe. (In other words, they've been around for many years, you can get the source code, and the main distribution points are known to be virus-free, if that's a concern.)
If you are unable or unwilling to install third-party software on your DOS or Windows computer, your alternative is to select one of six different solutions that best fits your needs from #4.
Select one of the following methods:
|
I would be remiss if I did not give credit to several people who have been invaluable in providing key solutions over the years. These people include: Tom Lavedas, Ted Davis, "Outsider", Benny Pederson, John Savage, Herbert Kleebauer, Gerard Piette, and Timo Salmi. If I have forgotten to credit anyone else, please let me know and I'll remedy the omission.
Under 4DOS, getting data
into environment variables is simple. 4DOS is a commmand
interpreter (shell) replacement for COMMAND.COM
. It is
commercial software, written by JP Software,
so this solution requires that you have paid a license for 4DOS,
4NT, or
"Take Command" (the current
single-user cost is about $70). However, to me the numerous advantages of
4DOS are worth parying for. 4NT is preferred for users of Windows NT and
Windows 2000.
echo 1234 | input %%myvar ; puts "1234" into %myvar% set myvar=%@line[MYFILE,5] ; puts line 6 into %myvar% set myfar=%@word[4,%@line[MYFILE,6]] ; puts 5th word of line 7 into %myvar%
The only notable thing about this syntax is that words and lines are numbered beginning with 0, not 1. Thus the desired word and line number should be decremented by 1 when passing the value to the 4DOS or 4NT %@line[] function. 4DOS also permits words to be pulled from the right end of a line, as well.
For those who prefer freeware solutions and don't need/want the immense
power offered by 4DOS/4NT, here is the easiest solution for most people. It
uses separate utilities, such as STRINGS
or ASET
,
to directly create the environment variables. These utilities permit a
variety of string manipulation, as well as math functions.
If you run Windows NT, Win2000, or WinXP, click here.
I recommend STRINGS
v2.5 by Douglas Boling (PC
Magazine) and ASET
v1.0 by Richard Breuer because they are
freeware and are easily available on the Internet. STRINGS
comes
with ASM source code included. Consider these four examples of obtaining
console output:
echo Greetings! # prints "Greetings!" to screen wc -l < myfile # prints "1234" to screen echo. | date | find "199" # prints "Current date is Thu 12-17-1998" calc 7 + 33 # prints "40" to screen
You will find that STRINGS
and ASET
easily put these into variables:
echo Greetings! | STRINGS hi=ASK # puts "Greetings!" into %hi% wc -l < myfile | STRINGS num=ASK # puts "1234" into %num% STRINGS hi=LEFT Greetings!,10 # puts "Greetings!" into %hi% STRINGS today=date # uses internal date function STRINGS now=time # uses internal time function STRINGS sum=ADD 7,33 # uses internal math function calc 7 + 33 | STRINGS sum=ASK # or use calc to create %sum% echo Greetings! | ASET hi=line # puts "Greetings!" into %hi% wc -l < myfile | ASET num=line # puts "1234" into %num% ASET hi='Greetings!' # puts "Greetings!" into %hi% ASET today=date # uses internal date function ASET now=time # uses internal time function ASET sum=7+33 # uses internal math function calc 7 + 33 | ASET sum=line # or use calc to create %sum%
If your data exists on disk, both STRINGS
and ASET
are able to access diskfiles on a line-oriented basis. For example:
STRINGS var=read MYFILE,3 # put line 3 of MYFILE into %var% ASET var=LINE(3,'MYFILE') # put line 3 of MYFILE into %var%
If you want to prompt the user for a string of words or letters, and then
put that string in a variable, both STRINGS
and ASET
can do that easily. ASET
's getstr()
function will
also permit cursor movement foreward and backward, including insert and
delete, before pressing the RETURN key. These examples should
illustrate:
Sample STRINGS usage: Sample ASET usage: @echo off @echo off strings var=ask Enter your full name: echo Enter your full name: echo The user typed /%var/. aset var=line echo The user typed /%var/.
Advanced STRINGS features: @echo off :: variable length a max of 20 chars, "1" means mask chars with asterisks strings var=ask Enter your password: ,20,1 echo The password is :%var: Advanced ASET features: @echo off :: use CLS to move the prompt to line 1 cls echo Enter your password: :: args are (max-length,'default string',row,column) aset var=getstr(20,'joshua',1,21) echo. echo The password is :%var:
Both STRINGS
and ASET
have a wide range of
functions to generate data on time, date, math, file, disk, memory, and other
values, and to transform or parse strings (lowercase, uppercase, substrings,
count words, etc.). They are extremely flexible, not too large (14k and 100k
respectively), and are free of charge.
STRINGS v2.5 ftp://ftp.zdnet.com/pcmag/1992/1222/strings.zip (filesize: 75k) strings.zip (local disk copy) ASET v1.0 ftp://ftp.uwasa.fi/pc/batchutil/aset10.zip (filesize: 80k) ftp://ftp.simtel.net/pub/simtelnet/msdos/batchutl/aset10.zip
STRINGS
and ASET
(and most other environment
manipulation utilities) do not work under Windows NT and Windows 2000, even
though they work as advertised in a DOS session or a DOS window under
Microsoft Windows 9x. Why is this, and can it be corrected?
Last question first: No, the problem cannot be corrected. Though Windows 2000
may complain "not enough environment space" when running STRINGS
or ASET
, the problem is not due to insufficient
environment space. The problem is caused by the fact that STRINGS
and ASET
both use the DOS interrupt call INT 21
to alter environment variables. Windows NT and Windows 2000 are incompatible
with this common technique. Here are some alternate solutions:
To prompt the user for a value and then put their keyboard reply into an environment variable, run this command:
SET /P VARNAME=Please enter your name:
SET will display the prompt "Please enter your name:" to the user, who is expected to type a string of lettes and press ENTER. Whatever they type will be stored in the variable %VARNAME, where it can be retrieved for later operations.
This technique doesn't work with Windows NT. However, Simon Sheppard (www.ss64.com) wrote this script using Windows Scripting Host (present on NT and Win2K machines) to store user input into an environment variable:
:: Input1.cmd - A routine to prompt the user for an input string.
:: Requires WSH version 1.0 or later.
:: Input string is stored in the variable v_input
:: Use optional command line argument UCASE to convert input to all uppercase.
:: usage:
:: input1
:: input1 ucase
@ECHO off
SETLOCAL
SET v_vbs=%TEMP%\~tmp.VBS
SET v_cmd=%TEMP%\~tmp.cmd
ECHO Set oFS=CreateObject("Scripting.FileSystemObject")>%v_vbs%
ECHO oFS.OpenTextFile("CON",2).Write "Enter a string: ">>%v_vbs%
ECHO S=%1(Trim(oFS.OpenTextFile("CON",1).Readline))>>%v_vbs%
ECHO oFS.CreateTextFile("%v_cmd%",2).Write "set v_input=">>%v_vbs%
ECHO oFS.OpenTextFile("%v_cmd%",8).Write S>>%v_vbs%
cscript.exe //nologo %v_vbs%
CALL %v_cmd%
DEL %v_vbs%
DEL %v_cmd%
SET v_input
ENDLOCAL & SET v_input=%v_input%
One workaround is to place the command(s) to these utilities in the file
called C:\WINNT\AUTOEXEC.NT
or
. The file
AUTOEXEC.NT
is a "batch" file and it runs like
AUTOEXEC.BAT
does in normal MS-DOS. If you are able, execute
ASET
or STRINGS
from within
AUTOEXEC.NT
. Every time CMD.EXE or COMMAND.COM is executed,
AUTOEXEC.NT
will be executed, and any variables which are set
there will persist for the life of the CMD or COMMAND window.
There's probably another workaround, but I don't know what it is right now. If someone else does, please e-mail me. Thanks!
This method does not require a prepared file like PREFIX.DAT
,
above. However, it does need an external string manipulation program like
sed
(stream editor) or awk
, which are available as
freeware for MS-DOS.
sed15/DOS ftp://ftp.simtel.net/pub/simtelnet/msdos/txtutl/sed15x.zip sed15/Win95 http://www.cornerstonemag.com/sed/sed15exe.zip gsed 3.02.80 http://www.student.northpark.edu/pemente/sed/sed3028a.zip GNU awk/DOS ftp://ftp.simtel.net/pub/simtelnet/gnu/gnuish/gawk306x.zip
Because sed
is fairly small (22k for sed15, 84k for gsed) as
compared to awk
(226k), I often prefer to use
sed
.
Wherever our data comes from, we must be able to prepend
"set value=" before the data. If the term is "Jan. 1, 2003",
we must be able to change it to "set value=Jan. 1, 2003". Sed
or
awk
are superb at doing this.
In Example 1, we'll use console output and sed
to put some
data into a variable. In Example 2, we'll get the data from disk and use
awk
to put the data into a variable. Both techniques use a DOS
batch file.
Example 1: Get today's date and put it into a variable, %DATE%
@echo off :: The output of 'date' in Windows 98 looks like this: :: Current date is Thu 04-11-2002 :: Enter new date (mm-dd-yy): echo. | date | sed "/2002/!d; s/.* /set date=/" >tmp_.bat :: call tmp_.bat echo Today's date is: [%DATE%] :: :: after processing, delete temp file quietly, unset the variable del tmp_.bat >NUL set date=
Example 2: Get John Doe's phone number from FOO.DAT
, and put
it into the variable %PHONE%
@echo off :: Look for name John Doe, get field #4 awk "/John Doe/ {print \"set phone=\" $4}" FOO.DAT >tmp_.bat call tmp_.bat echo John Doe's phone number is /%PHONE%/ :: del tmp_.bat >NUL set phone=
Of course, in situations like Example 2, you must write your sed or awk script to ensure that you don't end up with more than one line of data (and, optionally, that the total line length is under 127 characters).
Example 3: Prompt the user for a phrase and put it into the variable called %phr%
@echo off echo Enter a phrase and press the ENTER key: awk "{print \"set phr=\" $0;exit;}" >tmp_.bat call tmp_.bat echo The line of words typed is "%phr%" del tmp_.bat >NUL set phr=
Two things are needed: your data directed to disk and a batch file.
First, if your data will come from console output (such as the screen
output of ECHO, GREP, SED, WC, DATE, CALC, FIND,
etc.), you must
redirect the data to a disk file. The data must be one line only! For
example:
echo Some sample data > ANSWER.DAT grep "pattern" MYFILE.TXT > ANSWER.DAT sed -n "/regexp/p" MYFILE.TXT > ANSWER.DAT wc -l < MYFILE.TXT > ANSWER.DAT echo. | DATE | find "199" > ANSWER.DAT calc 87 * 55 > ANSWER.DAT find "this string" < MYFILE.TXT > ANSWER.DAT
However you obtain your data (sed, wc, calc, etc.), the point is that
the data may not be longer than one line. In fact, since MS-DOS cannot
handle command lines longer than 127 characters, ANSWER.DAT
must be
several characters shorter than that. (Technically, 127 minus the
length of the string "set your_variable_name=", which will be
prepended to ANSWER.DAT
later on.)
Second, in the batch file we need to be able to issue the command
set MYVAR={the contents of ANSWER.DAT go here}
This is a difficult task, since MS-DOS doesn't offer an easy way to prepend "set MYVAR=" to a file. There are at least six different solutions available under MS-DOS without resorting to third-party utilities (even though using a third-party program is the easiest solution). Technically, there are two others that I am omitting here because, in my opinion, they are more obtuse or difficult to use than the ones listed below. If you know of any DOS-only solutions I haven't remembered, please let me know. Thanks!
Normal DOS text files and batch files end all lines with two consecutive bytes: a carriage return (Ctrl-M, hex 0D, or ASCII 13) and a linefeed (Ctrl-J, hex 0A or ASCII 10). In the batch file, you must be able to embed a Ctrl-J in the middle of a line.
Many text editors have a way to do this: via a Ctrl-P followed by
Ctrl-J (DOS EDIT
with Win95/98, VDE
), via a Ctrl-Q prefix (Emacs,
PFE
), via direct entry with ALT and the numeric keypad (QEdit,
Multi-Edit
), or via a designated function key (Boxer
). Other editors
absolutely will not support this (Notepad, Editpad, EDIT
from MS-DOS
6.22 or earlier; VIM
can insert a linefeed only in binary mode,
but not in its normal text mode).
If you can do it, your batch file might look like this:
@echo off :: assume that the datafile exists already in ANSWER.DAT echo set myvar=^J | find "set" >PREFIX.DAT copy PREFIX.DAT+ANSWER.DAT VARIAB.BAT call VARIAB.BAT echo Success! The value of myvar is: [%myvar%]. :: erase temp files ... for %%f in (PREFIX.DAT ANSWER.DAT VARIAB.BAT) do del %%f >NUL
Where you see the ^J on line 3 above, the linefeed should be embedded at that point. Your editor may display it as a square box with an embedded circle.
The drawback to this method is that some e-mail or Usenet programs automatically convert lone Ctrl-J characters to normal 2-byte line endings, so your batch files may not survive well over the Net.
This solution doesn't require any special text editor, but does require user assistance in making the batch file.
@echo off :: assume that the datafile exists already in ANSWER.DAT echo. echo Type the words "set myvar=" (don't type the quote marks) echo and then immediately after the = sign, press Control-Z! copy con PREFIX.DAT copy PREFIX.DAT+ANSWER.DAT VARIAB.BAT call VARIAB.BAT echo Success! The value of myvar is: [%myvar%]. :: erase temp files ... for %%f in (PREFIX.DAT ANSWER.DAT VARIAB.BAT) do del %%f >NUL
Note that this batch file cannot run unattended and that the user
must manually create the PREFIX.DAT
file on-the-fly. Do not press
the ENTER key before pressing Control-Z.
The following solution requires no user intervention, nor does it
require single linefeeds in a DOS batch file. DEBUG.EXE
is included
in all standard distributions of MS-DOS and is in Windows 95/98 in
C:\WINDOWS\COMMAND
, so you can use it unless someone has deleted it.
@echo off :: assume that the datafile exists already in ANSWER.DAT echo e 100 "set myvar=" > TEMP.FIL echo n PREFIX.DAT >> TEMP.FIL for %%i in (rcx a w q) do echo %%i >> TEMP.FIL debug < TEMP.FIL copy PREFIX.DAT+ANSWER.DAT VARIAB.BAT call VARIAB.BAT echo Success! The value of myvar is: [%myvar%]. :: erase temp files ... for %%f in (PREFIX.DAT ANSWER.DAT VARIAB.BAT TEMP.FIL) do del %%f >NUL
Many people are skittish about using DEBUG
and rightfully so, since
DEBUG
can crash a hard drive or delete files and directories.
Therefore, here is an explanation of what the previous commands
actually do. I obtained these commands from Dan Gookin's Guide to
Underground DOS 6.0 (Bantam Books, 1993), pp. 187-190, which tells
quite a lot about using DEBUG
. For the cautious user, here's what
these commands mean to DEBUG
:
e 100 "set myvar=" ; at base address 100, Enter this "string" n PREFIX.DAT ; "n" means set a filename called PREFIX.DAT rcx ; in Register CX, set the size of the file a ; filesize A hex (10 bytes) put in register CX w ; Write the file set by "n", i.e., PREFIX.DAT q ; Quit DEBUG
(To be written)
(To be written)
(To be written)
Warning! In all these methods, note that they use temporary files
(ANSWER.DAT, PREFIX.DAT, VARIAB.BAT
, and TEMP.FIL
). We have assumed
that files with these names don't already exist on disk. If they do
exist, the batch file overwrites them without asking permission. If
these filenames might conflict with files on your computer, change
them to a filename not likely to be used, such as "#PRE!.FIX
" or
"}TMP{.FIL
" (yes, both these are legitimate filenames under MS-DOS).
These different methods should help make handling DOS environment variables easier. Please write me if you find any of these examples to be unclear or in need of improvement.
Kind regards,
Eric Pement (Acts 17:29-31, Titus 2:11-14)
[eof]