Board logo

标题: [ZT]纯DOS下读取文件首行为变量,一句话 » [打印本页]

作者: electronixtar     时间: 2006-10-11 04:36    标题: [ZT]纯DOS下读取文件首行为变量,一句话 »

原文见二楼
ECHO EXIT|%COMSPEC%/KPROMPT E100'SET VAR='$_RCX$_8$_NFILE1.BAT$_W$_Q|DEBUG>NUL
[ Last edited by electronixtar on 2006-11-4 at 11:32 PM ]
作者: electronixtar     时间: 2006-10-11 04:45    标题: [ZT]纯DOS下读取文件首行为变量,一句话

http://lf.8k.com/BAT/FVAR.TXT

  Quote:
::::::::::::::                         ::::::::::::::::::::::::::::::
Last Modified: 2001-07-29              :
Author       : Laura Fairhead          :
::::::::::::::                         ::::::::::::::::::::::::::::::
                                       

How do I get a single line text file into an environment variable?
------------------------------------------------------------------

A common problem encountered in DOS for which the solution is not
obvious is how one might read a line of text in a file into a
DOS environment variable.

For example to get the current directory one might start with;

CD>FILE.TXT

If only you could do something like;

SET VAR=readfile("FILE.TXT")

But DOS has no such abilities.

Here are presented a number of the known ways to perform this function,
throughout the same naming convention is used;

FILE.TXT = the single line text file to read
VAR      = the name of the variable to get the line into


Auxillary file solution
~~~~~~~~~~~~~~~~~~~~~~~

This is the standard book solution.

(i) At the command prompt enter "COPY CON FILE1.BAT", type the
text "SET VAR=" and terminate the line by pressing CTRL+Z first,
then ENTER. This creates a file that contains the text "SET VAR="
with no newline on the end.

(ii) Use the following code in your batch file;

======================================================================
COPY FILE1.BAT FILE2.BAT
TYPE FILE.TXT >>FILE2.BAT
CALL FILE2.BAT
DEL FILE2.BAT
======================================================================

After this VAR will be set with the contents of FILE.TXT

The problem with this method is that it requires an auxillary file that
goes together with the main batch program. The above lines work
fine if they are run while in the same directory as the auxillary file
however will fail if it is not. It is desirable for the auxillary file
to be stored together with the batch file in it's directory, then
there are 2 possibilites to solve this problem

(A) "hard-code" the location of FILE1.BAT. So if the batch file
    and FILE1.BAT are put into C:\UTILS you would use the following lines

======================================================================
COPY C:\UTILS\FILE1.BAT FILE2.BAT       <--- path to FILE1.BAT hardcoded
TYPE FILE.TXT >>FILE2.BAT
CALL FILE2.BAT
DEL FILE2.BAT
======================================================================

Hardcoding PATHs to files is generally considered extremely bad programming
practice, but this maybe sufficient in certain contexts (for example
if the batch is for floppy).

(B) Locate the directory of the batch & FILE1.BAT using code.

This is the usual solution for professional software, however
to do this using only batch language is extremely awkward and it
requires around a dozen or so lines of code.


DEBUG script edit solution
~~~~~~~~~~~~~~~~~~~~~~~~~~

The problem with the "AUXILLARY FILE" algorithm could easily be
solved by getting the batch file to create FILE1.BAT.

There is a problem with this however;

ECHO SET VAR=>FILE1.BAT

Creates a file with the text "SET VAR=" and a newline appended. There
is no way possible to convince the ECHO command not to append the
newline, it does this with anything that it outputs.

Here is where DEBUG can help out;

======================================================================
ECHO E100"SET VAR=">$
FOR %%_ IN (RCX 8 NFILE1.BAT W Q) DO ECHO %%_>>$
DEBUG <$ >NUL
======================================================================

The first 2 lines of the above create a DEBUG script file "$";

======================================================================
E100"SET VAR="
RCX
8
NFILE1.BAT
W
Q
======================================================================

When fed into DEBUG it creates a 8 byte file consisting of the text
"SET VAR=" with no newline on the end. So having created FILE1.BAT
(in the current directory) the program can go on to use it to
complete the algorithm;

======================================================================
ECHO E100"SET VAR=">$                                              (1)
FOR %%_ IN (RCX 8 NFILE1.BAT W Q) DO ECHO %%_>>$                   (2)
DEBUG <$ >NUL                                                      (3)
DEL $                                                              (4)
TYPE FILE.TXT>>FILE1.BAT                                           (5)
CALL FILE1.BAT                                                     (6)
DEL FILE1.BAT                                                      (7)
======================================================================

Many variations on this are possible and common. The creation
of the file can actually be done much more compactly;

======================================================================
ECHO EXIT|%COMSPEC%/KPROMPT E100'SET VAR='$_RCX$_8$_NFILE1.BAT$_W$_Q|DEBUG>NUL
======================================================================

This replaces lines 1-4 in the above. The temporary file is now implicit
(handled by DOS pipes) so doesn't require deletion. The first two stages
in the pipeline produce the following output;

======================================================================
E100'SET VAR='
RCX
8
NFILE1.BAT
W
QEXIT
======================================================================

The PROMPT command has been utilized in order to output newlines
directly here. With COMMAND /K switch the arguement is executed
as a shell command and then it continues by executing standard input.
There is no need for an additional '$_' after the 'Q' because debug
only looks at 'Q' itself and ignores any trailing garbage on the
line.

SED solution
~~~~~~~~~~~~

SED is an industry standard UNIX utility and a very good, compact,
freeware port for DOS exists;

ftp://ftp.simtel.net/pub/simtelnet/msdos/txtutl/sed15x.zip

SED can solve many tasks standing on its head that plain DOS finds either
impossible or _extremely_ awkward. This is one of them;

======================================================================
SED "s/^/SET VAR=/" FILE.TXT >FILE1.BAT
CALL FILE1.BAT
DEL FILE1.BAT
======================================================================


ASCII CODE
~~~~~~~~~~

ASCII code is machine code that can be represented by printable ASCII
characters. Often this is very carefully crafted by hand so that the
program does not contain any binary values which are unprintable ASCII
codes (less than hex20), shell special characters (<, >, |...)
or possibly untransportable 8-bit characters (greater than hex7F).

The result is a machine code .COM program which can be created simply
using ECHO (program ) >CODE.COM. This is very flexible and transportable
code and reduces file access overhead;

=====================================================================
ECHO XPYP[*'CC-\1P\QX,=P,APZ5O!PQ2O~5aaI~}Ksx>_.COM
=====================================================================

This is an ASCII code program that when run simply ECHO's text
but with no newline on the end.

So;

_ SET VAR=>FILE1.BAT

Then creates the desired base FILE1.BAT

Of course having created the _.COM echo program it can be used again
and again throughout the batch, only being deleted on exit. It is
obviously useful for a great deal more than this one particular
task.

Of course the full atomic operation will be peformed now by the
lines;

=====================================================================
ECHO XPYP[*'CC-\1P\QX,=P,APZ5O!PQ2O~5aaI~}Ksx>_.COM
_.COM SET VAR=>FILE1.BAT
TYPE FILE.TXT>>FILE1.BAT
CALL FILE1.BAT
DEL FILE1.BAT
DEL _.COM
=====================================================================

Here is a full disassembly of the machine code generated
with commenting;

=====================================================================
;on entry to .COM program:
;      SP=FFFE, a 0 word is on the stack
;      DS=ES=SS=CS
;      CS:0->PSP
;
;      contrary to some information out there AX is not always 0
;      this is the 4th revision of this code, the 3rd assumed AX=0000
;
;      Since all the segment registers are the same and remain the
;      same throughout they are not mentionned any further

;AX=0000 CX=0000 BX=0000
1777:0100 58                X      POP     AX
1777:0101 50                P      PUSH    AX
1777:0102 59                Y      POP     CX
1777:0103 50                P      PUSH    AX
1777:0104 5B                [      POP     BX

;[BX]=[0]=BYTE AT PSP OFFSET 0
;the word at PSP offset 0 is a INT 20 instruction (CD 20)
;before a COM program is entered 0 is pushed to the stack
;this means that a RET instruction will 'JMP 0' execute
;the INT 20 and consequently return to DOS
;however here is used the value 'CD'
;and AH=00-CD =33

1777:0105 2A 27             *'     SUB     AH,[BX]

;BX=0002
1777:0107 43                C      INC     BX
1777:0108 43                C      INC     BX

;AX=01A4
1777:0109 2D 5C 31          -\1    SUB     AX,315C

;SP=01A4
1777:010C 50                P      PUSH    AX
1777:010D 5C                \      POP     SP

;AX=0000
1777:010E 51                Q      PUSH    CX
1777:010F 58                X      POP     AX

;AX=00C3
1777:0110 2C 3D             ,=     SUB     AL,3D

;[01A2]=C3 00
1777:0112 50                P      PUSH    AX

;AX=0082
1777:0113 2C 41             ,A     SUB     AL,41

;DX=0082
1777:0115 50                P      PUSH    AX
1777:0116 5A                Z      POP     DX

;AX=21CD
1777:0117 35 4F 21          5O!    XOR     AX,214F

;[01A0]=CD 21 C3 00
1777:011A 50                P      PUSH    AX

;
; now at: 01A0: CD 21      INT 21
;         01A2: C3         RET
;         01A3: 00
;
;stack pointer is just below it at 01A0 (predecrementing).
;This is adjusted deliberately to be as far away from the
;program as possible (for stack space) but still being
;able to reach this _generated_ code with a relative jump. *[1]
;

;and now a 0 word is pushed. This is so that when the 'RET'
;at 01A2 is encountered the program will 'JMP 0' and hence
;INT 20 and return to DOS

;get 0 word ready for next POP (the RET)
1777:011B 51                Q      PUSH    CX

;CL=00 XOR [0080] = [0080]
;      The number of characters in the command line tail (in the PSP)
1777:011C 32 4F 7E          2O~    XOR     CL,[BX+007E]

;AX=40xx   (21CD XOR 6161=40xx)
;  only the value in AH is important
1777:011F 35 61 61          5aa    XOR     AX,6161

;  this has been preparing for a DOS call;
;
;  AH=40        write handle function
;  BX=0001      DOS stdout
;  CX=#chars    chars to write
;  DX=0082      start of text to output
;
;DX is set to 0082 instead of 0081 (the actual start of the command line
;tail data in the PSP) because DOS starts writing the command tail
;from/including the character deliminating the command. So if you started
;at 0081 the result of 'ECHOCOMMAND hello' would be the text ' hello'
;just incrementing to 0082 doesn't solve the problem completely. CX needs
;to be decremented so that 1 less character is output.

1777:0122 49                I      DEC     CX

;Now if CX has decremented to -1 (from 0) we must skip the call. JNG
;will jump if ZF=1 OR SF<>OF. The overflow flag must be clear due to
;the limited range of CX, so that evaluates to ZF=1 OR SF=1. So it
;skips the output call if there are no characters to output as well.

1777:0123 7E 7D             ~}     JNG     01A2

;BX=0001
1777:0125 4B                K      DEC     BX

;CF=0 after the XOR AX,6161 by definition and the intermediate instructions
;do not change it so this is simply a 'JMP'. Of course JMP = 0EBh
;which is outside the range of printable ASCII characters (020h to 07Eh)
;that are allowed in the program.

1777:0126 73 78             sx     JNC     01A0

---------------------------------------------------------------------

*[1]:
       Certain instructions that _need_ to be executed can not be
       represented with the ASCII codes 020h - 07Eh, so the method
       has to be that those instructions are generated somehow.
       I had seen other ASCII machine code programs that did this
       by modifying later parts of themselves so that when they fell
       through to those stages the instructions were there. There is
       a serious problem with self modifying code like this on 486 and
       earlier processors, the prefetch queue is loaded ahead of code
       execution (on 486 I think it is maybe as much 32 bytes) and
       any modifications to code that falls in that range will only
       effect memory--- the preloaded(unmodified) instructions will
       still execute. On the Pentium they changed the processor logic
       so that a write in the range of the prefetch queue will cause
       it to be immediately reloaded from memory. On 486 and earlier
       you need to have some sort of JMP instruction to cause it to
       be reloaded first. Try making a program this small with a jump
       instruction to another part of the program.....

=====================================================================


~~

[ Last edited by electronixtar on 2006-11-4 at 11:31 PM ]
作者: zouzhxi     时间: 2006-10-11 04:47
http://lf.8k.com/BAT/CK.TXT

  Quote:
CLOCK - time display utility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is a little application that keeps an updated display
of the current time on the screen. The time is displayed
using large characters (either 8x7 or 8x14 character cells
per character ) in a choice of two styles- either a normal
monochrome font or a colour graphics font. The program
automatically selects one of these two styles depending
on whether or not it finds ANSI.SYS installed but that
behaviour can be overridden by a command line option.
There is also an option to select between normal and
double size characters for the display.


Character generation
~~~~~~~~~~~~~~~~~~~~
The large characters are generated from a built in font
which is 8x8 pixels in size. As the characters are generated
one by one they are written to a display buffer array in
8 environment variables, one for each line;

%L!%           row1
%L!!%          row2
%L!!!%         row3
%L!!!!%        row4
%L!!!!!%       row5
%L!!!!!!%      row6
%L!!!!!!!%     row7
%L!!!!!!!!%    row8

Naming the variables in this way makes it easier for the
batch to use them by using a bang counter variable.

The main working routine is a program generated batch
file named %TMP0%. This is produced by the code at :DGVE
(right down until before :RTIME), the main program simply
redirects the output of this routine to the file %TMP0%.

The structure of the %TMP0% file is part of a very important
set of general structures for batch files that allows
many data-base type operations. The first line of the
file is simply;

%1

Which allows the file to be called with the first parameter
as 'GOTO:record_name'. And that record will be retrived.
Here, the record is the graphics of a single digit and
it is appended directly to the display buffer variables;

:C2
SET L!=%L!%  2222  
SET L!!=%L!!% 22  22
SET L!!!=%L!!!%     22
SET L!!!!=%L!!!!%    22  
SET L!!!!!=%L!!!!!%   22   
SET L!!!!!!=%L!!!!!!%  22   
SET L!!!!!!!=%L!!!!!!!% 222222
SET L!!!!!!!!=%L!!!!!!!!%        
GOTO OUT

The prefix 'C' is necessary because there have been reported
problems with a numeric as the first character of a label name
and it can cause various difficulties with batch program also.
:DGVE also generates records for all the other digits 0-9
and also a record for the colon character (called C_3A) and
the period (called C_2E). The last generated line of the %TMP0%
file is a ':OUT' label to allow each record to exit from the
file after being called.

Because it takes a while to create this file the program
does not delete it on exit, and it performs a test on
startup to see if the file already exists. The implementation
actually 'tags' the first line of the file;

%1 % !<id> %

The variable ' !<id> ' obviously can't exist (since it can't
be SET) so always evaluates to nothing, so the text in-between
allows various information to be put into the file without
affecting it's operation (although any SPACE characters added must
be considered carefully). In this case '<id>' is a special
identifier the program uses so that later it can determine
if the file was generated by it, and also that it is the type
of file it needs (the program actually generates one of 2 files
depending on whether the display is ANSI or normal).

:DGV is called to generate each character record. The parameters
to the call are;

CALL %0 . GOTO:DGV labelname mark row1left row1right ..... row8left row8right

'labelname' is simply the name of the label that is going to be
the first line of the record.

'mark' is a single character to use to represent each filled square
in the display representation. Unfilled squares are always represented
as a SPACE character. :DGV does not actually use the 'mark' character
if it the display style is ANSI graphics, with ANSI graphics the 'mark'
character is always character 0xFE (255 dec), a small block.

Then comes the actual graphic data which is in hexadecimal. Each parameter
is a 4 pixel chunk, start from the top left of the character and going
left to right, top to bottom. This format allows the font to be stored
very compactly and also to be generated quickly and easily from data
using standard utilities- I didn't have to design the font for this
program I just used a quick 'awk' script to convert it from a font
file.

Getting the current time
~~~~~~~~~~~~~~~~~~~~~~~~





~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full listing                                             TESTED: DOS7
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ECHO OFF
IF !%1==!. %2
%COMSPEC% /E:4096 /C %0 . GOTO:START %1
GOTO OUT
:START
FOR %%_ IN (0 1) DO SET TMP%%_=%TEMP%.\@%%_.BAT
SET COM=%COMSPEC%/E:4096
SET F=%0
ECHO EXIT|%COM%/KPROMPT SET ESC=$E$_:>%TMP1%
CALL %TMP1%
MEM/C |FIND "ANSI ">NUL
SET ANSI=TRUE
IF ERRORLEVEL 1 SET ANSI=FALSE
:: use ANSI graphics - set to FALSE here to stop
:: SET ANSI=FALSE
:: vertical enlarge option - change to set default
SET VE=FALSE
:L4
SHIFT
IF !%2==! GOTO K5
IF !%2==!BIG SET VE=TRUE
IF !%2==!SMALL SET VE=FALSE
IF !%2==!NORMAL SET ANSI=FALSE
IF NOT !%2==!/? GOTO L4
ECHO %F% [/?] [NORMAL] [BIG] [SMALL]
ECHO batch clock utility
ECHO NORMAL  specifies not to use ANSI.SYS colour graphics
ECHO.        which is default if the program detects it is installed
ECHO BIG     uses double height character font
ECHO SMALL   uses normal height character font (default)
ECHO.
GOTO QUIT
:K5
SHIFT
IF NOT !%3==! GOTO L4
FOR %%_ IN (C0 C1) DO SET %%_=
IF %ANSI%==TRUE SET C0=%ESC%[1;31m
IF %ANSI%==TRUE SET C1=%ESC%[0m
IF NOT EXIST %TMP0% GOTO K3
FIND "%% !@FBBC%ANSI% %%" <%TMP0% >NUL
IF NOT ERRORLEVEL 1 GOTO K4
:K3
ECHO PLEASE WAIT...
%COM%/C %F% . GOTO:DGVE >%TMP0%
:K4
:L1
SET _=
ECHO EXIT|%COM%/KPROMPT $T&|%COM%/C %F% . GOTO:RTIME >%TMP1%
CALL %TMP1%
CALL %F% . GOTO:WRT %_%
CHOICE /C%ESC%N /TN,01>NUL
IF ERRORLEVEL 2 GOTO L1
:QUIT
IF EXIST %TMP1% DEL %TMP1%
GOTO OUT
:WRT
SHIFT
SHIFT
IF !%8==! %F% . GOTO:WRT1 0 %1 : %2 %3 . %4 %5
%F% . GOTO:WRT1 %1 %2 : %3 %4 . %5 %6
:WRT1
FOR %%_ IN (! !! !!! !!!! !!!!! !!!!!! !!!!!!! !!!!!!!!) DO SET L%%_=
:L0
SET _=C%3
IF %3==: SET _=C_3A
IF %3==. SET _=C_2E
CALL %TMP0% GOTO:%_%
SHIFT
IF NOT !%3==! GOTO L0
ECHO EXIT|%COM% /K PROMPT SET _=$D$_:>%TMP1%
CALL %TMP1%
CLS
FOR %%_ IN (. .) DO ECHO.
IF %VE%==FALSE FOR %%_ IN (. . .) DO ECHO.
ECHO. ____________________________________________________________________
ECHO.   %_%
ECHO.[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
ECHO.[  %C0%%L!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!%%C1%  ]
ECHO.[  %C0%%L!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!%%C1%  ]
ECHO.[  %C0%%L!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!%%C1%  ]
ECHO.[  %C0%%L!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!%%C1%  ]
ECHO.[  %C0%%L!!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!!%%C1%  ]
ECHO.[  %C0%%L!!!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!!!%%C1%  ]
ECHO.[  %C0%%L!!!!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!!!!%%C1%  ]
ECHO.[____________________________________________________________________]
ECHO                                                       [ESC] To exit
ECHO  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IF %ANSI%==TRUE ECHO %ESC%[30m%ESC%[K%ESC%[0m%ESC%[A
GOTO OUT
:DGVE
ECHO %%1 %% !@FBBC%ANSI% %%
CALL %F% . GOTO:DGV C_2E . 0 0 0 0 0 0 0 0 0 0 1 8 1 8 0 0
CALL %F% . GOTO:DGV C0 0 3 C 6 6 6 E 7 E 7 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C1 1 1 8 3 8 1 8 1 8 1 8 1 8 7 E 0 0
CALL %F% . GOTO:DGV C2 2 3 C 6 6 0 6 0 C 1 8 3 0 7 E 0 0
CALL %F% . GOTO:DGV C3 3 3 C 6 6 0 6 1 C 0 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C4 4 0 C 1 C 3 C 6 C 7 E 0 C 0 C 0 0
CALL %F% . GOTO:DGV C5 5 7 E 6 0 7 C 0 6 0 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C6 6 1 C 3 0 6 0 7 C 6 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C7 7 7 E 0 6 0 C 1 8 3 0 3 0 3 0 0 0
CALL %F% . GOTO:DGV C8 8 3 C 6 6 6 6 3 C 6 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C9 9 3 C 6 6 6 6 3 E 0 6 0 C 3 8 0 0
CALL %F% . GOTO:DGV C_3A : 0 0 0 0 1 8 1 8 0 0 1 8 1 8 0 0
ECHO :OUT
GOTO OUT
:DGV
SET S= %=%
SET M=%4
IF %ANSI%==TRUE SET M=?SET C=!
ECHO :%3
:DGL
SET _=
FOR %%_ IN (CALL SHIFT) DO %%_ %F% . GOTO:DGE %5
FOR %%_ IN (CALL SHIFT) DO %%_ %F% . GOTO:DGE %5
ECHO SET L%C%=%%L%C%%%%_%
SET C=%C%!
IF NOT %C%==!!!!!!!!! GOTO DGL
ECHO GOTO OUT
GOTO OUT
:DGE
IF %3==0 SET _=%_%%S%%S%%S%%S%
IF %3==1 SET _=%_%%S%%S%%S%%M%
IF %3==2 SET _=%_%%S%%S%%M%%S%
IF %3==3 SET _=%_%%S%%S%%M%%M%
IF %3==4 SET _=%_%%S%%M%%S%%S%
IF %3==5 SET _=%_%%S%%M%%S%%M%
IF %3==6 SET _=%_%%S%%M%%M%%S%
IF %3==7 SET _=%_%%S%%M%%M%%M%
IF %3==8 SET _=%_%%M%%S%%S%%S%
IF %3==9 SET _=%_%%M%%S%%S%%M%
IF %3==A SET _=%_%%M%%S%%M%%S%
IF %3==B SET _=%_%%M%%S%%M%%M%
IF %3==C SET _=%_%%M%%M%%S%%S%
IF %3==D SET _=%_%%M%%M%%S%%M%
IF %3==E SET _=%_%%M%%M%%M%%S%
IF %3==F SET _=%_%%M%%M%%M%%M%
GOTO OUT
:RTIME
FOR %%_ IN ( 0 1 2 3 4 5 6 7 8 9) DO IF ERRORLEVEL 1%%_ SET _=%_% %%_
CHOICE /C&&&&&&&&&0123456789>NUL
IF ERRORLEVEL 10 GOTO RTIME
ECHO SET _=%_%
EXIT
:OUT

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[ Last edited by zouzhxi on 2006-10-11 at 04:50 ]
作者: zouzhxi     时间: 2006-10-11 04:53
http://lf.8k.com/BAT/LC.TXT

  Quote:
@ECHO OFF
::***********RENAME ALL FILES IN CURRENT DIRECTORY TO LOWERCASE************
::SET THIS TO 'NUL' TO BIN OUTPUT
SET U=CON
::SET UP DOSKEY MACROS
SET Q=FOR %%
SET R= IN ("SET T
SET S=") DO %%
:GOTO
DOSKEY ENTER=SET T=$*$T%%Q%%n%%R%%=%%S%%%%T%%$T%%Q%%e%%R%%=%%S%%%%T%%$T%%Q%%w%%R%%=%%S%%%%T%%$T%%Q%%" "%%R%%=%%S%%%%T%%$T%%Q%%t%%R%%=%%S%%%%T%%$T%%Q%%i%%R%%=%%S%%%%T%%>$
DOSKEY INVALID=%%Q%%m%%R%%=%%S%%%%T%%$T%%Q%%e%%R%%=%%S%%%%T%%$T%%Q%%:%%R%%=%%S%%%%T%%$T%%Q%%" "%%R%%=%%S%%%%T%%$TREN "%%T%%" "%%T%%"$TECHO "%%T%%" to "%%T%%"$G%%U%%>>$
DOSKEY CURRENT=REM
::(REINSTALL DOSKEY IF OUT OF SPACE)
FC NUL $|FIND "*">NUL
IF NOT ERRORLEVEL 1 FOR %%_ IN ("ECHO OUT OF MACRO SPACE.. REINSTALLING DOSKEY" "DOSKEY /R" "GOTO:GOTO") DO %%_
::GET FILENAME LIST READY TO PROCESS
DIR/L/B>$
ECHO.>>$
TIME<$>$.BAT
DEL $
ECHO INVALID>>$.BAT
ECHO EXIT>>$.BAT
::NOW $.BAT READY CALL IT
CTTY NUL
%COMSPEC% /K<$.BAT
CTTY CON
DEL $.BAT
FOR %%_ IN (Q R S T U) DO SET %%_=
FOR %%_ IN (ENTER INVALID CURRENT) DO DOSKEY %%_=


作者: electronixtar     时间: 2006-10-11 05:32
……还是不要把和主题无关的帖子发过来的好……
作者: done     时间: 2006-10-11 07:02
这个是dos还是汇编啊
作者: weilong888     时间: 2006-10-11 08:51
这些可不大容易搞清楚啊。
作者: needed     时间: 2006-10-11 22:24
我还是没有看懂,如果是借助外部命令的话,不用这么复杂.
如果只用内部命令,我看不到例子
作者: zouzhxi     时间: 2006-10-11 23:21
我也是在这个地方找的,不懂它的用法...

地址:http://lf.8k.com/BAT/CK.TXT

  Quote:
CLOCK - time display utility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This is a little application that keeps an updated display
of the current time on the screen. The time is displayed
using large characters (either 8x7 or 8x14 character cells
per character ) in a choice of two styles- either a normal
monochrome font or a colour graphics font. The program
automatically selects one of these two styles depending
on whether or not it finds ANSI.SYS installed but that
behaviour can be overridden by a command line option.
There is also an option to select between normal and
double size characters for the display.


Character generation
~~~~~~~~~~~~~~~~~~~~
The large characters are generated from a built in font
which is 8x8 pixels in size. As the characters are generated
one by one they are written to a display buffer array in
8 environment variables, one for each line;

%L!%           row1
%L!!%          row2
%L!!!%         row3
%L!!!!%        row4
%L!!!!!%       row5
%L!!!!!!%      row6
%L!!!!!!!%     row7
%L!!!!!!!!%    row8

Naming the variables in this way makes it easier for the
batch to use them by using a bang counter variable.

The main working routine is a program generated batch
file named %TMP0%. This is produced by the code at :DGVE
(right down until before :RTIME), the main program simply
redirects the output of this routine to the file %TMP0%.

The structure of the %TMP0% file is part of a very important
set of general structures for batch files that allows
many data-base type operations. The first line of the
file is simply;

%1

Which allows the file to be called with the first parameter
as 'GOTO:record_name'. And that record will be retrived.
Here, the record is the graphics of a single digit and
it is appended directly to the display buffer variables;

:C2
SET L!=%L!%  2222  
SET L!!=%L!!% 22  22
SET L!!!=%L!!!%     22
SET L!!!!=%L!!!!%    22  
SET L!!!!!=%L!!!!!%   22   
SET L!!!!!!=%L!!!!!!%  22   
SET L!!!!!!!=%L!!!!!!!% 222222
SET L!!!!!!!!=%L!!!!!!!!%        
GOTO OUT

The prefix 'C' is necessary because there have been reported
problems with a numeric as the first character of a label name
and it can cause various difficulties with batch program also.
:DGVE also generates records for all the other digits 0-9
and also a record for the colon character (called C_3A) and
the period (called C_2E). The last generated line of the %TMP0%
file is a ':OUT' label to allow each record to exit from the
file after being called.

Because it takes a while to create this file the program
does not delete it on exit, and it performs a test on
startup to see if the file already exists. The implementation
actually 'tags' the first line of the file;

%1 % !<id> %

The variable ' !<id> ' obviously can't exist (since it can't
be SET) so always evaluates to nothing, so the text in-between
allows various information to be put into the file without
affecting it's operation (although any SPACE characters added must
be considered carefully). In this case '<id>' is a special
identifier the program uses so that later it can determine
if the file was generated by it, and also that it is the type
of file it needs (the program actually generates one of 2 files
depending on whether the display is ANSI or normal).

:DGV is called to generate each character record. The parameters
to the call are;

CALL %0 . GOTO:DGV labelname mark row1left row1right ..... row8left row8right

'labelname' is simply the name of the label that is going to be
the first line of the record.

'mark' is a single character to use to represent each filled square
in the display representation. Unfilled squares are always represented
as a SPACE character. :DGV does not actually use the 'mark' character
if it the display style is ANSI graphics, with ANSI graphics the 'mark'
character is always character 0xFE (255 dec), a small block.

Then comes the actual graphic data which is in hexadecimal. Each parameter
is a 4 pixel chunk, start from the top left of the character and going
left to right, top to bottom. This format allows the font to be stored
very compactly and also to be generated quickly and easily from data
using standard utilities- I didn't have to design the font for this
program I just used a quick 'awk' script to convert it from a font
file.

Getting the current time
~~~~~~~~~~~~~~~~~~~~~~~~





~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full listing                                             TESTED: DOS7
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ECHO OFF
IF !%1==!. %2
%COMSPEC% /E:4096 /C %0 . GOTO:START %1
GOTO OUT
:START
FOR %%_ IN (0 1) DO SET TMP%%_=%TEMP%.\@%%_.BAT
SET COM=%COMSPEC%/E:4096
SET F=%0
ECHO EXIT|%COM%/KPROMPT SET ESC=$E$_:>%TMP1%
CALL %TMP1%
MEM/C |FIND "ANSI ">NUL
SET ANSI=TRUE
IF ERRORLEVEL 1 SET ANSI=FALSE
:: use ANSI graphics - set to FALSE here to stop
:: SET ANSI=FALSE
:: vertical enlarge option - change to set default
SET VE=FALSE
:L4
SHIFT
IF !%2==! GOTO K5
IF !%2==!BIG SET VE=TRUE
IF !%2==!SMALL SET VE=FALSE
IF !%2==!NORMAL SET ANSI=FALSE
IF NOT !%2==!/? GOTO L4
ECHO %F% [/?] [NORMAL] [BIG] [SMALL]
ECHO batch clock utility
ECHO NORMAL  specifies not to use ANSI.SYS colour graphics
ECHO.        which is default if the program detects it is installed
ECHO BIG     uses double height character font
ECHO SMALL   uses normal height character font (default)
ECHO.
GOTO QUIT
:K5
SHIFT
IF NOT !%3==! GOTO L4
FOR %%_ IN (C0 C1) DO SET %%_=
IF %ANSI%==TRUE SET C0=%ESC%[1;31m
IF %ANSI%==TRUE SET C1=%ESC%[0m
IF NOT EXIST %TMP0% GOTO K3
FIND "%% !@FBBC%ANSI% %%" <%TMP0% >NUL
IF NOT ERRORLEVEL 1 GOTO K4
:K3
ECHO PLEASE WAIT...
%COM%/C %F% . GOTO:DGVE >%TMP0%
:K4
:L1
SET _=
ECHO EXIT|%COM%/KPROMPT $T&|%COM%/C %F% . GOTO:RTIME >%TMP1%
CALL %TMP1%
CALL %F% . GOTO:WRT %_%
CHOICE /C%ESC%N /TN,01>NUL
IF ERRORLEVEL 2 GOTO L1
:QUIT
IF EXIST %TMP1% DEL %TMP1%
GOTO OUT
:WRT
SHIFT
SHIFT
IF !%8==! %F% . GOTO:WRT1 0 %1 : %2 %3 . %4 %5
%F% . GOTO:WRT1 %1 %2 : %3 %4 . %5 %6
:WRT1
FOR %%_ IN (! !! !!! !!!! !!!!! !!!!!! !!!!!!! !!!!!!!!) DO SET L%%_=
:L0
SET _=C%3
IF %3==: SET _=C_3A
IF %3==. SET _=C_2E
CALL %TMP0% GOTO:%_%
SHIFT
IF NOT !%3==! GOTO L0
ECHO EXIT|%COM% /K PROMPT SET _=$D$_:>%TMP1%
CALL %TMP1%
CLS
FOR %%_ IN (. .) DO ECHO.
IF %VE%==FALSE FOR %%_ IN (. . .) DO ECHO.
ECHO. ____________________________________________________________________
ECHO.   %_%
ECHO.[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~]
ECHO.[  %C0%%L!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!%%C1%  ]
ECHO.[  %C0%%L!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!%%C1%  ]
ECHO.[  %C0%%L!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!%%C1%  ]
ECHO.[  %C0%%L!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!%%C1%  ]
ECHO.[  %C0%%L!!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!!%%C1%  ]
ECHO.[  %C0%%L!!!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!!!%%C1%  ]
ECHO.[  %C0%%L!!!!!!!%%C1%  ]
IF %VE%==TRUE ECHO.[  %C0%%L!!!!!!!%%C1%  ]
ECHO.[____________________________________________________________________]
ECHO                                                       [ESC] To exit
ECHO  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IF %ANSI%==TRUE ECHO %ESC%[30m%ESC%[K%ESC%[0m%ESC%[A
GOTO OUT
:DGVE
ECHO %%1 %% !@FBBC%ANSI% %%
CALL %F% . GOTO:DGV C_2E . 0 0 0 0 0 0 0 0 0 0 1 8 1 8 0 0
CALL %F% . GOTO:DGV C0 0 3 C 6 6 6 E 7 E 7 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C1 1 1 8 3 8 1 8 1 8 1 8 1 8 7 E 0 0
CALL %F% . GOTO:DGV C2 2 3 C 6 6 0 6 0 C 1 8 3 0 7 E 0 0
CALL %F% . GOTO:DGV C3 3 3 C 6 6 0 6 1 C 0 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C4 4 0 C 1 C 3 C 6 C 7 E 0 C 0 C 0 0
CALL %F% . GOTO:DGV C5 5 7 E 6 0 7 C 0 6 0 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C6 6 1 C 3 0 6 0 7 C 6 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C7 7 7 E 0 6 0 C 1 8 3 0 3 0 3 0 0 0
CALL %F% . GOTO:DGV C8 8 3 C 6 6 6 6 3 C 6 6 6 6 3 C 0 0
CALL %F% . GOTO:DGV C9 9 3 C 6 6 6 6 3 E 0 6 0 C 3 8 0 0
CALL %F% . GOTO:DGV C_3A : 0 0 0 0 1 8 1 8 0 0 1 8 1 8 0 0
ECHO :OUT
GOTO OUT
:DGV
SET S= %=%
SET M=%4
IF %ANSI%==TRUE SET M=?SET C=!
ECHO :%3
:DGL
SET _=
FOR %%_ IN (CALL SHIFT) DO %%_ %F% . GOTO:DGE %5
FOR %%_ IN (CALL SHIFT) DO %%_ %F% . GOTO:DGE %5
ECHO SET L%C%=%%L%C%%%%_%
SET C=%C%!
IF NOT %C%==!!!!!!!!! GOTO DGL
ECHO GOTO OUT
GOTO OUT
:DGE
IF %3==0 SET _=%_%%S%%S%%S%%S%
IF %3==1 SET _=%_%%S%%S%%S%%M%
IF %3==2 SET _=%_%%S%%S%%M%%S%
IF %3==3 SET _=%_%%S%%S%%M%%M%
IF %3==4 SET _=%_%%S%%M%%S%%S%
IF %3==5 SET _=%_%%S%%M%%S%%M%
IF %3==6 SET _=%_%%S%%M%%M%%S%
IF %3==7 SET _=%_%%S%%M%%M%%M%
IF %3==8 SET _=%_%%M%%S%%S%%S%
IF %3==9 SET _=%_%%M%%S%%S%%M%
IF %3==A SET _=%_%%M%%S%%M%%S%
IF %3==B SET _=%_%%M%%S%%M%%M%
IF %3==C SET _=%_%%M%%M%%S%%S%
IF %3==D SET _=%_%%M%%M%%S%%M%
IF %3==E SET _=%_%%M%%M%%M%%S%
IF %3==F SET _=%_%%M%%M%%M%%M%
GOTO OUT
:RTIME
FOR %%_ IN ( 0 1 2 3 4 5 6 7 8 9) DO IF ERRORLEVEL 1%%_ SET _=%_% %%_
CHOICE /C&&&&&&&&&0123456789>NUL
IF ERRORLEVEL 10 GOTO RTIME
ECHO SET _=%_%
EXIT
:OUT

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


作者: electronixtar     时间: 2006-10-12 02:46
楼上的是一个纯DOS下的批处理时钟
作者: 3742668     时间: 2006-10-12 06:44
本主题亮点在顶楼的 ASCII code 部分。
作者: 不得不爱     时间: 2006-10-12 22:07
——————————————————版务纪录——————————————————
执行:qwe1234567
说明:2 、3、4、5楼的帖子发到不相关的主题:[共同参与][挑战思路][批处理处理浮点运算]
操作:分割2 、3、4、5楼的帖子到这个主题上
提示:请不要把帖子发到不相关的主题上!
————————————————————————————————————————

作者: redtek     时间: 2006-10-13 00:37
顶~~
作者: amao     时间: 2006-10-14 15:19


  Quote:
Originally posted by needed at 2006-10-11 22:24:
我还是没有看懂,如果是借助外部命令的话,不用这么复杂.
如果只用内部命令,我看不到例子

在纯DOS下,如何借助外部命令,读取文件首行为变量?
我是新手,很想知道这个问题,还望赐教。
作者: hxuan999     时间: 2006-11-23 00:55
晕呀