|
From the News Page 2 | |
A new (and advanced?) method for writing elements in a FOR loop.
$H Back Spaces. Time fractions and COMMAND /K (Jump to solution)
Choose/(Choice) [Back Space] and [Enter] keys are now permitted.
Get a variable of words (a list of words) into single variables.
Write a file named with the current time. (Won't work on DOS 6).
Perform a SHIFT command before CALLing a batch file named L.BAT.
An universal recursive module along with WSH (see abbreviations)
Reverse order of elements.
Examples from a News Group [MSDOS.BATCH] June 2, 01
: A new (and advanced?) method for writing elements in a FOR loop.
abc,1
hello
abc,2
hello
abc,3
hello
bye-bye
@echo off
for %%v in (1 hello 2 hello 3 hello bye-bye) do echo.abc,%%v
The character of ASCII value 8 is .
The above example uses four of those Back Space characters in the front
of those elements (they are eating the leading "abc,")
So, let's debug:
@echo off >~.bat
for %%v in (e0'mmddyy' 8 i71 7 i71 9 i71 q) do echo
.o70,%%v>>~.bat
DEBUG < ~.bat | find "7"/v > ~.bat
for %%v in (CLS type del) do %%v ~.bat
^^^
Caution:
If you are using the Back Space character to manipulate an output, then
you should test your batch program both with and without DOSKEY loaded.
If the DOSKEY is loaded, then the above batch example won't work unless
the CLS command is specified as above.
Notes:
The above e0'mmddyy' is just an extra dummy label. So one could name it
anything after the e; (a valid HEX numb such as FACE, 2BAD or whatever)
or one could simply remove it.
e 2BAD 'century'
O 70,32
I 71
e0 'year'
o70,9
i71
e0 'month+day:[SNIPED]...'
q (bye-bye)
The backspace can be eliminated from the output by PIPING the text
through a copy of the command processor.
:: An example to remove the fractions from time
@echo off
echo @prompt $_echo;set Time$Q$T$H$H$H$_exit$_> ~tmp.bat
%comspec%/e:2048/c~tmp.bat |%comspec%/k|find "="|find/v ";">~tmp.bat
for %%v in (call del) do %%v ~tmp.bat
for %%v in (. . .%Time%) do echo%%v
set Time=
The string stored in the variable 'TIME' does NOT contain backspaces.
-- Posted by Tom Lavedas.
Before my examination of this, I would first say that the output from
time, here in Denmark (OS: Danish Win98), would be as shown below:
US, AM/PM, DK,
-------------------------
8:00:00 AM, Time= 8.00.00
8:00:00 PM, Time=20.00.00
and thereby the last line would fails AM
for %%v in (. . .%Time%) do echo%%v
for %%v in (. . . 8.00.00) do echo8.00.00
The $H in PROMPT means Back Space, so, is DOSKEY loaded or not
loaded? This causes a lot of the same kind of errors (periodical).
Now what if the PROMPT contains an equal sign as: "PROMPT $Q$p$g IOSYS" ?
The answer is that it would fails. Moreover, files are written or ruined!
And what if the folder/directory is named "set Time=" ?
The answer is that this would also fails.
Okay, the last one is not very probable but anyhow, this old solution needs
some modifications.
Start of examination/inspection.
An inspection of the first output from the source before the destination.
Caution: "FILE_1" equals "FILE_2" ONLY if DOSKEY isn't loaded.
%comspec%/c SOURCE.bat > ~TMP | %comspec%/k > FILE_1
%comspec%/c SOURCE.bat | %comspec%/k > FILE_2
Below are some test files, which can be used to examine some of all those
error messages and can be used to understand some of the problems.
Notis that some of the below characters are invisible and that this
also complicates this case a bit.
@echo off> ~
for %%v in (rcx E n~1.bat e100''D''D''A'REM:ERROR'D''A ) do echo:%%v>>~
for %%v in (w n~2.bat e100''D''D''A''D''A'REM:OK!'D''A) do echo:%%v>>~
for %%v in (w n~3.bat e100''D''A'REM:OK!!!'D''D''A w q) do echo:%%v>>~
debug<~
erase:~
Remove fractions.
The below batch/DOS program works and I have tested it on Win98
both with and without the DOSKEY.
@echo off
for %%v in (set prompt) do %%v:::=%prompt%
echo @prompt:echo:@set:Time$Q$T$H$H$H$_exit>~tmp.bat
%comspec% /c ~tmp.bat |%comspec% /k> ~tmp.bat
for %%v in (CLS call del) do %%v ~tmp.bat
for %%v in (prompt:%::% echo. echo.) do %%v
echo. (%Time%)
for %%v in (Time ::) do set:%%v=
The following two batch files works with two conditions.
1. The PROMPT must not contains = (equal sign)
2. If $p is included in the PROMPT, then current PATH must not contains =
@echo off
echo @prompt echo;set Time$Q$T$H$H$H$_exit> ~tmp.bat
%comspec% /c ~tmp.bat | %comspec% /k | find "=" | find ";"/v > ~tmp.bat
for %%v in (cls call del) do %%v ~tmp.bat
echo on
@for %%v in (%Time%) do set Time=%%v
@echo off
echo @prompt echo;set:H$Q$T$H$H$H$_exit>%temp%.\~tmp.bat
%comspec%/c%temp%.\~tmp.bat|%comspec%/k|find "="|find ";"/v>%temp%.\~tmp.bat
for %%v in (cls call) do %%v %temp%.\~tmp.bat
for %%v in (%H%) do set H=%%v
echo.. | choice /n/c%H%> %temp%.\~%H%
if not errorlevel 3 rem> %temp%.\~0%H%
for %%? in (0 1 2 3 4 5 6 7 8 9) do if exist %temp%.\~%%??.??.* set H=%%?
for %%? in (0 1 2 3 4 5 6 7 8 9) do if exist %temp%.\~?%%?.??.* set H=%H%%%?
for %%? in (0 1 2 3 4 5 6 7 8 9) do if exist %temp%.\~??.%%??.* set M=%%?
for %%? in (0 1 2 3 4 5 6 7 8 9) do if exist %temp%.\~??.?%%?.* set M=%M%%%?
for %%? in (0 1 2 3 4 5 6 7 8 9) do if exist %temp%.\~??.*.%%?? set S=%%?
for %%? in (0 1 2 3 4 5 6 7 8 9) do if exist %temp%.\~??.*.?%%? set S=%S%%%?
for %%v in (. .Time: . .H:[%H%] .M:[%M%] .S:[%S%] .) do echo%%v
del %temp%.\~*
for %%v in (H M S) do set %%v=
The following two examples 1.) and 2.), uses the FIND command once:
PROMPT with $p included:
1.) Both the prompt and current path must not contains " % ":
echo @prompt echo set %%%%%%%% Time$Q$T$H$H$H$_exit> ~tmp.bat
%comspec% /c ~tmp.bat | %comspec% /k | find " %% " > ~tmp.bat
2.) Path whatever but a variable named \\rabit mustn't exist:
echo @prompt echo set %%%%%%%%\\rabit%%%%%%%% Time$Q$T$H$H$H$_exit> ~tmp.bat
%comspec% /c ~tmp.bat | %comspec% /k | find " %%\\rabit%% " > ~tmp.bat
The following file was created before I found the significant "@" in the
above "@set" command. Hmmm, now I would like to say: if Micky soft can't
create a file to be used on simple DOS, then, how should they be able to
make anything more complicated than a file named "DOSKEY.COM".
@echo off %( TEST.BAT )%
for %%v in (set prompt) do %%v:::=%prompt%
:: prompt [PROMPT-- ( echo:set:Time$g ) --PROMPT]
echo @prompt:echo:set:Time$Q$T$H$H$H$_exit>~tmp.bat
%comspec% /c ~tmp.bat |%comspec% /k |find "Time" |find "::"/v> ~tmp.bat
for %%v in (cls call del) do %%v ~tmp.bat
goto Next
ALTERNATIVE:
mem /c | find "DOSKEY" > nul
if errorlevel 1 goto 0
:1 (DOSKEY is loaded)
%comspec% /c ~tmp.bat |%comspec% /k |find "Time"> ~tmp.bat
for %%v in (cls call del) do %%v ~tmp.bat
goto Next
:0 (DOSKEY isn't loaded)
%comspec% /c ~tmp.bat |%comspec% /k |find "::"/v> ~tmp.bat
for %%v in (call del) do %%v ~tmp.bat
:Next
for %%v in (prompt:%::% echo. echo.) do %%v
echo.(%Time%)
for %%v in (Time ::) do set:%%v=
for %%v in (echo echo SET echo pause cls) do %%v:
Conclusion:
To write a similar program like this with FIND filters instead of
manipulating the PROMPT, that's logical impossible.
(Jump to solution).
Write a file named with the current time
Notis: It works on a Danish Win98 (without colons in the date format).
The following can be used to write a file named with the current time but it
won't work in an old DOS 622, anyhow, someone could ask for a Win9x solution
and if so, then the following may be a very brief solution:
@echo off
echo prompt %prompt%>%temp%.\~.bat
prompt rem$G$G$T$H$H$H$_:|echo EXIT|%comspec%/k>>%temp%.\~.bat
for %%v in (call del) do %%v %temp%.\~.bat
Jump to similar solutions, just click here.
: Replacement of CHOICE.com:
: CHOOSE.bat permitted both the [Back Space] and the [Enter] keys.
:
: The second line contents lots of ASCII FFh (255 dec) characters:
: To input more than one word, (both first and last name), just click here
..
@echo off
for %%v in (cls echo echo.ÿÿÿÿÿÿ(Inputÿyourÿfirstÿname)) do %%v:
fc/n nul/Lb1 con|find "1">%temp%.\~id.bat
for %%v in (L e3D'set'9'%%1' w q) do echo %%v3D>>%temp%.\~id.bat
type %temp%.\~id.bat|debug %temp%.\~id.bat>nul
type %temp%.\~id.bat|find "3D"/v>%temp%.\~id.bat
CALL %temp%.\~id who
for %%v in (%who%) do set who=%%v
for %%v in (Yourÿnameÿisÿ%who% ÿ) do echo. %%v
set who=
del %temp%.\~id.bat
for %%v in (set:cmdline pause cls) do %%v=
: Benny, PS. "fc CON CON" if two lines of input; name and address.
:: fc con/lb1/n con|find "1"|sort>%temp%.\~id.bat but if
: the first input was Abc and the next was abc, then it
: would not be the same as abc and Abc (reverce order).
: If you'll try line number three as "fc con/lb1/n con"
: etc., SORT, then also remember this:
: CTTY nul
: CALL ~id who
: CTTY con
:
: Want another entry than 3D? for example F8, just use:
:
:: FOR %%v in (L fF8L7'set'9'%%1'3D'' w q) do echo %%vF8
:: etc... and TYPE %temp%.\~id.bat | find "F8" /v etc...
Get a variable of words (a list of words) into single variables.
Notis: The below file named ~gt.bat should be named %temp%.\~gt.bat instead.
@echo off > ~gt.bat
set List= A list of ten words which goes to each variable
:: 1 2 3 4 5 6 7 8 9 10
REM One line to make a program file:
for %%e in (%List%) do echo for %%%%L in (e hif) do s%%%%Lt %%1=%%e>>~gt.bat
REM Use the file:
CALL ~gt L1 L2 L3 L4 L5 L6 L7 L8 L9 L10
REM Show the result:
echo RESULT: (%L1% %L2% %L3% %L4% %L5% %L6% %L7% %L8% %L9% %L10%)
REM Clean up:
for %%v in (1 2 3 4 5 6 7 8 9 10 ist) do set L%%v=
del ~gt.bat
GOTO EOF (2) --Notes:
Instead of the above "REM One line to make"..., the below would also be ok:
REM Four lines to make a program file:
for %%v in (@goto:%%1' :') do echo %%v>>~gt.bat
for %%v in (%List%) do echo prompt shift$_set %%%%1$Q%%v$_>>~gt.bat
echo::'' >> ~gt.bat
%comspec% /c~gt.bat|find /v "$">> ~gt.bat
REM Use the file:
CALL ~gt;' L1 L2 L3 L4 L5 L6 L7 L8 L9 L10
If the above alternative were used, then one could ask:
Now, what if my list of words looks like the following?
set List=$d $t
Answer: %L1% would contains the current date.
%L2% would contains the current time.
Here's another example (same method as above):
..
@echo off
for %%v in (cls echo echo.______(Input_Your_Name)) do %%v:
fc /Lb1 /n nul con |find "1" >%temp%.\~id.bat
for %%v in (L e3D'set'9'%%1' w q) do echo %%v3D>>%temp%.\~id.bat
type %temp%.\~id.bat|debug %temp%.\~id.bat>nul
type %temp%.\~id.bat|find "3D"/v>%temp%.\~id.bat
call %temp%.\~id who
set what=echo prompt shift$_set %%%%1$Q>%temp%.\~id.bat
for %%v in (@goto:%%1' :') do echo.%%v>>%temp%.\~id.bat
for %%v in (Time:;$t Date;$d %windir% $p $v) do %what%%%v$_>>%temp%.\~id.bat
for %%v in (Drive;$n: Path;%path% Me:;%who%) do %what%%%v$_>>%temp%.\~id.bat
echo::'' >> %temp%.\~id.bat
%comspec% /c%temp%.\~id.bat|find "$"/v>>%temp%.\~id.bat
call %temp%.\~id;' w1 w2 w3 w4 w5 w6 w7 w8 w9 wa wb wc wd we wf wg wh wi
for %%v in (%w1% %w2% %w3% %w4% %w5% %w6% %w7% %w8% %w9%) do echo. %%v
for %%v in (%wa% %wb% %wc% %wd% %we% %wf% %wg% %wh% %wi%) do echo. %%v
for %%v in ( ho hat 1 2 3 4 5 6 7 8 9 a b c d e f g h i ) do set w%%v=
del %temp%.\~id.bat
for %%v in (set:cmdline pause cls) do %%v=
:EOF (2)
Jump to a similar file, just click here.
To use "$H" (truncate with Back Spaces), follow this link.
Shortly after this were finished, an universal method were
developed but a documentation isn't finished: %COMSPEC% /k
Perform a SHIFT command before CALLing a batch file named L.BAT
Wild Strange and Unknown syntax along with the character: @.
@ECHO OFF > L.bat
@ECHO SHIFT >> L.bat
@ECHO ECHO. (%%1) (%%2) (%%3) >> L.bat
ECHO Press [Enter] or write SHIFT and press [Enter] key to continue...
@FC /LB1 CON NUL | FIND /I "SHIFT"> NUL
@SET Shift=:
@IF NOT ERRORLEVEL 1 SET Shift=: % %
@ECHO.
@%Shift%CALL L.BAT A B C D
@SET Shift=
@GOTO EOF
Since a variable named as ACSII 32 (20 hex) isn't possible with contents,
then it would be suitable to be used as a stop/ending an input of spaces.
Examples:
SET Variable=% % This would set a variable to blank, (no contents).
SET Variable= % % This would set a variable to one space.
SET Variable= % % This would set a variable to two spaces, and so...
Notis that if you try to SET a variable to a colon and three spaces, then
the News Reader will truncate the spaces. So, it would not be possible to
post anything to a News Group/WEB along with a variable, SET to space(s).
Benny Pedersen, PS.
BTW, A general solution, which can be placed on the last line of a batch-
file. This syntax should gossip about (any)/all your forgotten variables:
FOR %%! IN (ECHO.EOF PAUSE CLS ECHO. SET ECHO. PAUSE CLS GOTO:EOF) DO %%!
Related links:
Wild Strange and Unknown syntax.
:EOF
An universal recursive module along with some WSH stuff
@echo off
@if (%1)==() for %%v in (start goto:eof(module)) do %%v /max %0 !
for %%v in ( echo echo." Hello World" echo pause cls ) do %%v.
:eof(module)
Purpose: Is to make sure that the %0 parameter is an usefull file reference.
Benny, PS. Below are some examples which are using the recursive module.
(Beware of the wrapped line number 4:)
@echo off
%1 if not exist %windir%\wscript.exe goto eof(bubble-@batch)
%1 for %%@ in (start goto:eof(bubble-@batch)) do %%@/max %0 ::
echo exit|%comspec%/kPROMPT e0'dim arr'd a'arr=array('$_rcx$_13$_w0$_q>%t
emp%.\@bubble.vbs
type %temp%.\@bubble.vbs |debug %temp%.\@bubble.vbs> nul
for %%v in (Hi hi) do echo "%%v",_>> %temp%.\@bubble.vbs
echo "Testing, Batch","B","C","A")>> %temp%.\@bubble.vbs
find "@"/v <%0>> %temp%.\@bubble.vbs
GOTO END @
EchoArray "Not sorted array:"
BubbleSort
EchoArray "Sorted array:"
sub EchoArray(V1)
wscript.echo vbcrlf & V1
dim i
for i=0 to ubound(arr)
wscript.echo i & " " & arr(i)
next
end sub
sub BubbleSort()
dim i,j,k
for i=0 to ubound(arr)
for j=i+1 to ubound(arr)
if arr(i)>arr(j) then
k=arr(i)
arr(i)=arr(j)
arr(j)=k
end if
next
next
end sub
:END @
start /wait %temp%.\@bubble.vbs
erase %temp%.\@bubble.vbs
:eof(bubble-@batch)
Here's another: (Beware of the wrapped line number 4:)
@echo off
%1 if not exist %windir%\wscript.exe goto eof(QuickSort@bat)
%1 for %%@ in (start goto:eof(QuickSort@bat)) do %%@/max %0 ::
echo exit|%comspec%/kPROMPT e0'dim arr'd a'arr=array('$_rcx$_13$_w0$_q>%t
emp%.\@QuickS.FBI
type %temp%.\@QuickS.FBI |debug %temp%.\@QuickS.FBI> nul
for %%v in (Hi hi) do echo "%%v",_>> %temp%.\@QuickS.FBI
echo "Testing, Batch","B","C","A")>> %temp%.\@QuickS.FBI
find "@"/v <%0 | find "Script" /v >> %temp%.\@QuickS.FBI
find "@"/v <%0 | find "Script" > %temp%.\@QuickS.CIA
copy /b %temp%.\@QuickS.CIA + %temp%.\@QuickS.FBI %temp%.\@QuickS.WSF>nul
GOTO END @
<package><job id="Job1"><script language="JScript">function jssort(arr) {
return arr.toArray().sort().join('\t')}</script><script language="VBScript">
EchoArray "Not sorted array:"
arr=split(jssort(arr),vbtab)
EchoArray "Sorted array:"
sub EchoArray(V1)
wscript.echo vbcrlf & V1
dim i
for i = 0 to ubound(arr)
wscript.echo i & " " & arr(i)
next
end sub
</script></job></package>
:END @
start /wait %temp%.\@QuickS.WSF
erase %temp%.\@QuickS.???
:eof(QuickSort@bat)
Related notes and abbreviations:
A wrapped line here is an OOPS line, which is more than 76 characters lon
g. AOD5/01p65; If ASP, then remove XML, job and package and add runat=server
EOF --> End Of File
TMP --> TeMPorary. -- For example a file named ~.tmp
ADO --> ActiveX Data Objects
ASP --> Active Server Page
VBS --> Visual Basic Script
WSF --> Windows Script File
WSH --> Windows Script Host
XML --> Extensible Markup Language
Snip Snap Gibberish:
AOD --> Alt om DATA, (a Danish PC magazine).
FBI --> File Been Ignored
CIA --> Cause Ignore Also
Reverse order of elements
-- Ver no 0: 7 lines and 305 bytes.
-- Comments: Old version.
@echo off
echo set r=;%%2%%r%%> %temp%.\~rev.bat
for %%v in ( %path% ) do echo %%1 call %%0 :: %%v>> %temp%.\~rev.bat
set r=
for %%v in (call del) do %%v %temp%.\~rev.bat
for %%v in (--------PATH: %path% --------REVERSED: %r%) do echo %%v
set r=
-- Ver no 1: 11 lines and 578 bytes.
-- Comments: No GOTO's.
@ECHO OFF
SET List= 1 2 3 4 5
SET R=
ECHO GOTO:%%1 Run> %temp%.\~r.bat
ECHO :Run>> %temp%.\~r.bat
FOR %%c in (%List%) do ECHO CALL %%0 S %%c>> %temp%.\~r.bat
FOR %%c in (GOTO:D :S SET :D) do ECHO %%c R=%%2 %%R%%>>%temp%.\~r.bat
FOR %%c in (CAL DE) do %%cL %temp%.\~r.bat
FOR %%c in (. ."[%List%]" ."[%R%]" .) do ECHO%%c
FOR %%c in (---Elements: %List% ÿ ---Reversed: %R%) do ECHO.%%c
FOR %%c in (List R) do SET %%c=
-- Ver no 2: 12 lines and 335 bytes.
-- Comments: Recursive.
@%1 ECHO OFF
SET List= 1 2 3 4 5
SET R=
CALL %0 GOTO:L %List%
FOR %%c in (. ."[%List%]" ."[%R%]" .) do ECHO%%c
FOR %%c in (---Elements: %List% ÿ ---Reversed: %R%) do ECHO.%%c
FOR %%c in (List R) do SET %%c=
GOTO EOF
:L
SET R=%2 %R%
IF NOT ()==(%3) FOR %%c in (SHIFT GOTO:L) do %%c
:EOF
|