|
willsort
元老会员
         Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
    『楼 主』:
[原创]无奈何签名代码略析
使用 LLM 解释/回答一下
无奈何签名代码略析
☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
引自 无奈何·中国DOS联盟 论坛签名
这个签名中的代码应用于 WinNT 系列系统(如WinXP)中,将代码内容复制粘贴到的 “开始-运行” 对话框中,可以看到无奈何兄的签名逐字显示。代码长度只有132B,但其中包含许多批处理编程技巧,有些我也是后来才慢慢注意到的。现在我将这段代码分成节段,将其中使用到的重要技巧略作提示,以飨读者,也请原作者无奈何兄和其他批处理达人批评斧正。
1、%ComSpec% /c
使用它的目的在于,在运行对话框中调用 set / for / pause 等“内部命令”,因为它们由 NT 系列操作系统中命令行环境的主体程序—— cmd “内部”所支持,并且只能在 cmd “内部”所使用。cmd 全名为 cmd.exe,位于 %SystemRoot%\system32\ 路径下,由环境变量 %ComSpec% 指示其完整的路径。因为它只能在 NT 系列环境下运行,所以实际上它与 cmd /c 是近似等效的。但是因为 %ComSpec% 中包含了 cmd.exe 所在的路径,因此在 cmd.exe 位置比较特殊或者 %path% 变量缺漏的特殊系统环境中也可以使用。详细内容可以在命令行环境中使用 cmd /? 查阅到。
因为 “运行” 位于 cmd 之外,所以只能调用具有独立可执行文件的“外部命令”,而 cmd 这个“外部命令”就充当了内部命令的“传声筒”,将一串 “内部命令”当作 cmd 的命令行参数,通过 /c 这一选项开关传递到 cmd 内部,交由 cmd 内部解释执行。在 /c 与其后的附加参数命令串之间,一般会插入空格,以增加代码的可读性;无奈何兄省略空格,正是他提到的“尽量字符最短”和“尽量晦涩难读”要求的体现。而如果在命令行环境中使用,并且用 cmd 代替 %ComSpec% ,则 cmd 与 /c 之间的空格也可省略。这些省略空格的用法,有时并不单纯出于精简代码的目的,而是为了应付某些命令或程序比较羸弱的字符串分析算法——我们有时需要将整个命令行当作一个字符串来处理,而许多命令行程序会将空格作为一个字符串的结束标记,比如 for 命令中的 (set) 部分。当然,这种同时兼容空格与无空格的用法,一方面体现出其兼容并包的灵活特性,另一方面也为许多命令行扩展程序增加了诸多困扰,这就只能说“剑有双刃”了。
另外, /c 之后也可以使用“外部命令”,比如后面出现的 ping ,当它在 %path% 中找不到时,需要指明其所在路径。
2、set,=何奈无── 。何奈可无是原,事奈无做人奈无
此节是将要显示的签名串逆序保存到环境变量中。变量名","的使用在这里有多重含义,除了“两个尽量”的原则外,它还作为 set 与其参数的分隔符,这又是命令行灵活性的例证了——既允许变量名使用非字母数字的字符,又允许这个字符做其它解释。与此异曲同工的还有上面提到的 cmd/c 中“/”,以及“=”“;”等许多字符,这我在旧帖中曾有论述,不太好找了,有兴趣的可以自己多用 cmd 加一些特殊字符来尝试。
签名串逆序的目的自然又是“尽量晦涩难懂”,这与后面 for 中的 (22;-1;0) 相呼应。
签名串前后的两个特殊字符,就是 ASCII 字符集中的响铃符,其 ASCII 码为07,属于 ASCII 码表中的控制区字符。因控制区字符大多有特殊含义,故使用“记事本”很难输入这个字符,可以使用 DOS 下的编辑器 EDIT,届时先键入 Ctrl+P 开启控制字符显示(即暂时关闭其转义特性),再键入 Ctrl+G (提示:G在字母表中的顺序是7,详细内容请参阅网络上 ASCII 码表的相关信息)即可得到这个字符,当然也可使用 UltraEdit 这类十六进制编辑器,直接键入其 ASCII 代码来输入它。因为 ASCII 控制区字符的显示字形并无统一约定,因此它在命令行环境下看起来像一个圆点,而大多数 Windows 的字体不再能正常显示它。但又因 ASCII 标准被吸收为 Unicode 标准中的一个基本平面,因此支持 Unicode 的 NT 系统仍会正确识别并解释这个在旧 DOS 时代就风靡一时的特殊字符。
3、&for,/l,%i,in,(22,-1,0)do,
“&”是命令分隔符,用来分隔一个命令行中的多个命令。Cmd.exe 运行第一个命令,然后运行第二个命令。因为“&”有连接多个命令的功能,所以也称为“命令连接符”。set 是它所连接的第一个命令,for 是第二个命令。需要注意的是,其后的 ping 语句前也存在一个“&”,虽然同是命令分隔符,却分属不同层级,前者分隔 %ComSpec% /c 中的 set 与 for,后者分隔 for 中的 call 与 ping。同类的分隔符还有|,&&,||等,详细内容请查阅Windows帮助“命令提示符”一节。
以后为 for 的前半节,属于 for 循环的控制部分,实现一个从22到0的逆序循环,替换变量为%i,将在以后的循环体语句块中出现,并被替换为自 22 到 0 这 23 个数字串;详细内容可以在命令行环境中使用 for /? 查阅到。(22,-1,0) 之外的其余逗号都可替换为空格,也可以替换为其它可用的参数分隔符(比如“;”“=”等,注意与命令分隔符的区别),如此使用仍然是“尽量晦涩难懂”的体现。
4、@call,set/p= %,:~%i,1%<nul
这是 for 语句块中的第一句代码,目的是根据替换变量 %i 从环境变量 %,% 中取出对应的字符,结合 for 的控制部分,即实现了签名串的逆序逐字显示。@的作用在于禁止其后的 call 语句在命令行中回显,因为 for 语句会创建一个新的命令运行环境来执行循环体中的多条语句,而在这个新环境中命令行回显是开启的。而 call 则实现了命令行转义字符 % 的二次替换:在 for 创建的新环境中依次替换 %i 为 22 到 0 这 23 个数字,在 call 再次创建的新环境中依次再替换 %,:~22,1% 至 %,:~0,1% 为签名串中的每个字符。
至于命令行如何分析出现的多个转义字符 % 及其所夹杂的替换变量、环境变量和命令行参数,这主要取决于“左侧优先于右侧”、“可替换优先于无可替换”这两个原则,再加上环境变量的延迟替换特性,请读者慢慢自行体会。
于是,这一句代码就最终替换为“set/p= (某个签名字符)<nul”,/p 的作用是将签名字符当作询问环境变量值的提示语输出,而这个环境变量是没有名字的,所以将不会有环境变量被保存。至于为何不用 echo 来显示字符,是因为 set/p 不会在显示完字符串后再显示一个换行,这样可以使所有的签名字符显示在一行而非一列上;= 后的空格是可以省略的,它显示在每个字符前,因此会增加字符间距,改进显示效果;<nul 则负责满足 set/p 所等待的输入,< 将 set/p 的输入设备由标准的控制台(CON,通常为键盘+屏幕)重定向为空设备(NUL),虽然它并不是一个实际存在的硬件设备,而只是一个软件意义上的概念,但它会像宇宙中的黑洞一样,“吞噬”所有指向它的输入流和输出流,在这里, set/p 的输入需求也被“吞噬”,因此它不会停下来等待用户的输入了。
5、&ping/n 1 127.1>nul
& 在第3节已做解释。ping 是一个用于网络环境的外部命令,用以向指定的 IP 地址发送一个“网际消息控制协议 (ICMP)”回响请求消息,详细内容请参考 Windows 帮助中的 ping 命令一节;这里使用它可以暂停少许时间,以实现逐字显示的效果,当然它的暂停时间比较短暂而且不很固定,建议将 n 后的数字 1 改为 2,这样暂停的时间将大约等于 1 秒,详细内容请参考。>nul 与第 5 节的 <nul 近似,只是此时 NUL 将作为输出设备,“吞噬” ping 命令所产生的所有输出信息。
后序
这篇文章的初衷,源于 maya0su 兄在中的建议,我准备以无奈何兄的签名为蓝本,修改出一个命令行版的批处理代码,能以较通用的方法逐字显示一段指定的文本。起初以为有签名代码做铺垫,稍做一些修改便应该可以实现,但是随着修改的深入,发现了一些比较麻烦的问题(主要是转义字符的兼容型问题),这才着手仔细研究签名代码,发现了以往不曾注意到的细节和对一些代码的错误理解,这才有了这篇原创文章。
其实签名代码中最重要的技巧便是转义字符的二次替换,而我当初错误的将之理解为延迟替换,这也是这篇文章出炉的重要原因之一。但是,当我试图详细解释其中机理时,却发现只能深入而不能浅出,很多内容都牵涉到命令行解释的复杂特性,没有官方文档或其它公开资料可以参考和佐证,而我自己的体会难免会有疏漏,为免贻误读者,只好以一句“自行体会”来含糊带过,说来不免惭愧,敬请广大读者谅解!
参考
批处理编程的异类——时钟(Clock)
http://www.cn-dos.net/forum/viewthread.php?tid=8905#pid54227
批处理参数问题一点谈
http://www.cn-dos.net/forum/viewthread.php?tid=17785
关于"set & echo"变量替换的延迟
http://www.cn-dos.net/forum/viewthread.php?tid=18050
Last edited by willsort on 2006-1-22 at 11:34 ]
### Analysis of the Signature Code by Wunaike
☆Start\Run (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
Quoted from the signature of Wunaike on the China DOS Union forum
This signature's code is applied in WinNT series systems (such as WinXP). Copy and paste the code content into the "Start - Run" dialog box, and you can see the signature of Brother Wunaike displayed character by character. The code is only 132B long, but it contains many batch programming skills, some of which I only gradually noticed later. Now I will divide this code into sections and briefly hint at the important skills used, to entertain readers. Also, please allow Brother Wunaike, the original author, and other batch processing experts to criticize and make corrections.
1. %ComSpec% /c
The purpose of using it is to call internal commands such as set / for / pause in the Run dialog box. Because they are supported by the main program of the command line environment in NT series operating systems - the "internal" of cmd, and can only be used within the "internal" of cmd. Cmd is full name cmd.exe, located in the %SystemRoot%\system32\ path, and its complete path is indicated by the environment variable %ComSpec%. Because it can only run in the NT series environment, in fact, it is approximately equivalent to cmd /c. But because %ComSpec% contains the path where cmd.exe is located, it can also be used in special system environments where the location of cmd.exe is special or the %path% variable is missing. Detailed content can be found by using cmd /? in the command line environment.
Because "Run" is outside cmd, only "external commands" with independent executable files can be called, and the cmd "external command" acts as a "mouthpiece" for internal commands, passing a string of "internal commands" as the command line parameters of cmd, and passing them to the internal of cmd for interpretation and execution by the option switch /c. Generally, a space is inserted between /c and the subsequent attached command string to increase the readability of the code; Brother Wunaike omits the space, which is the embodiment of the requirements he mentioned of "trying to make the characters as short as possible" and "trying to be obscure and hard to read". And if used in the command line environment and cmd is used instead of %ComSpec%, the space between cmd and /c can also be omitted. These usages of omitting spaces are sometimes not simply for the purpose of streamlining the code, but to deal with the relatively weak string analysis algorithms of some commands or programs - sometimes we need to treat the entire command line as a string, and many command line programs will use spaces as the end mark of a string, such as the (set) part in the for command. Of course, this kind of usage that is compatible with both spaces and no spaces reflects its flexible characteristics of being inclusive on the one hand, and also causes many troubles for many command line extension programs on the other hand. This can only be said that "a sword has two edges".
In addition, "external commands" can also be used after /c, such as the ping that appears later. When it cannot be found in %path%, the path where it is located needs to be specified.
2. set,=何奈无── 。何奈可无是原,事奈无做人奈无
This section saves the signature string to be displayed in reverse order in an environment variable. The use of the variable name "," has multiple meanings here. In addition to the principle of "two tries", it also acts as a separator between set and its parameters. This is another example of the flexibility of the command line - it allows the variable name to use non-alphanumeric characters, and also allows this character to be interpreted in other ways. Similarly, the "/" in cmd/c mentioned above, as well as many characters such as "=" and ";" are also like this. I have discussed this in old posts before, which are not easy to find. Those who are interested can try using cmd with some special characters by themselves.
The purpose of reversing the signature string is naturally also "trying to be obscure and hard to understand", which echoes with (22;-1;0) in the subsequent for.
The two special characters before and after the signature string are the bell characters in the ASCII character set, whose ASCII code is 07, and they belong to the control area characters in the ASCII code table. Because most control area characters have special meanings, it is difficult to input this character with "Notepad". You can use the DOS editor EDIT. At that time, first type Ctrl+P to turn on the control character display (that is, temporarily turn off its escape characteristics), and then type Ctrl+G (tip: G is in the 7th position in the alphabet. For detailed content, please refer to the relevant information of the ASCII code table on the Internet), and you can get this character. Of course, you can also use a hexadecimal editor such as UltraEdit to directly type its ASCII code to input it. Because the display glyphs of ASCII control area characters are not uniformly agreed upon, it looks like a dot in the command line environment, and most Windows fonts can no longer display it normally. But because the ASCII standard is absorbed as a basic plane in the Unicode standard, NT systems that support Unicode will still correctly recognize and interpret this special character that was popular in the old DOS era.
3. &for,/l,%i,in,(22,-1,0)do,
"&" is a command separator, used to separate multiple commands in a command line. Cmd.exe runs the first command, and then runs the second command. Because "&" has the function of connecting multiple commands, it is also called a "command connector". set is the first command it connects, and for is the second command. It should be noted that there is also an "&" before the subsequent ping statement. Although it is also a command separator, it belongs to different levels. The former separates set and for in %ComSpec% /c, and the latter separates call and ping in for. Similar separators also include |, &&, ||, etc. For detailed content, please refer to the "Command Prompt" section in Windows Help.
The following is the control part of for, which realizes a reverse loop from 22 to 0, replaces the variable with %i, and will appear in the subsequent loop body statement block, and is replaced with the 23 digital strings from 22 to 0; for detailed content, you can use for /? in the command line environment to find out. The other commas in (22,-1,0) can be replaced with spaces, or other available parameter separators (such as ";", "=", etc., note the difference from the command separator). Such usage is still the embodiment of "trying to be obscure and hard to understand".
4. @call,set/p= %,:~%i,1%<nul
This is the first line of code in the for statement block. The purpose is to take out the corresponding character from the environment variable %,% according to the replacement variable %i, and combined with the control part of for, that is, to realize the reverse character-by-character display of the signature string. The role of @ is to prohibit the subsequent call statement from echoing in the command line. Because the for statement will create a new command running environment to execute multiple statements in the loop body, and command line echoing is on in this new environment. And call realizes the secondary replacement of the command line escape character %: in the new environment created by for, %i is replaced with the 23 digital strings from 22 to 0 in turn, and in the new environment created again by call, %,:~22,1% to %,:~0,1% are replaced with each character in the signature string in turn.
As for how the command line analyzes the multiple escape characters % that appear and the replacement variables, environment variables, and command line parameters mixed in them, this mainly depends on the two principles of "left is prior to right" and "replaceable is prior to non-replaceable", plus the delayed replacement characteristic of environment variables. Please readers experience it by themselves slowly.
Thus, this line of code is finally replaced with "set/p= (a certain signature character)<nul". The function of /p is to output the signature character as a prompt for asking the value of the environment variable. And this environment variable has no name, so no environment variable will be saved. As for why not use echo to display the character, it is because set/p will not display a new line after displaying the string, so that all signature characters can be displayed in one line instead of one column; the space after = can be omitted, it is displayed in front of each character, so it will increase the character spacing and improve the display effect; <nul is responsible for satisfying the input that set/p is waiting for. < redirects the input device of set/p from the standard console (CON, usually keyboard + screen) to the null device (NUL). Although it is not a actually existing hardware device, but only a software concept, it will "swallow" all input streams and output streams pointing to it. Here, the input requirement of set/p is also "swallowed", so it will not stop to wait for the user's input.
5. &ping/n 1 127.1>nul
& has been explained in section 3. ping is an external command used in the network environment to send an "Internet Control Message Protocol (ICMP)" echo request message to the specified IP address. For detailed content, please refer to the ping command section in Windows Help; here it is used to pause for a short time to achieve the effect of character-by-character display. Of course, its pause time is relatively short and not very fixed. It is recommended to change the number 1 after n to 2, so that the pause time will be approximately equal to 1 second. For detailed content, please refer to . >nul is similar to <nul in section 5, except that at this time NUL will be used as the output device, "swallowing" all the output information generated by the ping command.
Postscript
The original intention of this article originated from Brother maya0su's suggestion in . I was going to modify a command line version of the batch code based on Brother Wunaike's signature, which can display a specified text character by character in a more general method. At first, I thought that with the signature code as a foreshadowing, a little modification should be able to realize it. But as the modification went deeper, I found some more troublesome problems (mainly the compatibility problem of escape characters), so I started to study the signature code carefully, and discovered some details that I didn't notice before and some wrong understandings of some codes . This is the reason why this original article came out.
In fact, the most important skill in the signature code is the secondary replacement of escape characters, and I originally mistakenly understood it as delayed replacement. This is also one of the important reasons for the emergence of this article. However, when I tried to explain the mechanism in detail, I found that I could only go deep but not explain it in a simple way. Many contents are related to the complex characteristics of command line interpretation. There are no official documents or other public materials to refer to and prove, and my own experience is inevitably incomplete. In order to avoid misleading readers, I have to use a sentence "experience by yourself" to be vaguely passed, which is a bit embarrassing to say. I sincerely ask for the understanding of the majority of readers!
References
A Heterogeneous Batch Programming - Clock (Clock)
http://www.cn-dos.net/forum/viewthread.php?tid=8905#pid54227
A Little Talk about Batch Processing Parameters
http://www.cn-dos.net/forum/viewthread.php?tid=17785
About the Delay of "set & echo" Variable Replacement
http://www.cn-dos.net/forum/viewthread.php?tid=18050
Last edited by willsort on 2006-1-22 at 11:34 ]
|

※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-1-21 22:37 |
|
|
bush
银牌会员
    
积分 2165
发帖 730
注册 2004-4-21
状态 离线
|
『第 2 楼』:
使用 LLM 解释/回答一下
看看,
好像这个是xp的,不能在纯dos下用吧?
Look,
It seems this is for XP, can't it be used under pure DOS?
|
|
2006-1-21 23:56 |
|
|
无奈何
荣誉版主
      
积分 1338
发帖 356
注册 2005-7-15
状态 离线
|
『第 3 楼』:
使用 LLM 解释/回答一下
谢谢 willsort 兄的抬举
这篇文章如果我来写的话,万万不能表达的如此清晰详尽。这段代码是我由偶然想法经过多次的尝试性修改最终完成的,最初的代码并不复杂,我有意识的试探着精简字符,其难度也不大。但兄能逆向拆解,可见功力比我高的不是一点半点。
来论坛的这些日子从兄及其他朋友那里也学到了不少东西。由于最近出差及忙于年终的一些事务有些日子没能上网,终于忙完,明天就要回老家过春节去了,又要度过半个多月没有网络的日子。预祝坛子里的朋友们新春快乐!
Thanks to the promotion of brother willsort.
If I were to write this article, I could never express it so clearly and in detail. This code was finally completed by me after multiple tentative modifications from an accidental idea. The original code was not complicated. I consciously tried to simplify the characters, and the difficulty was not great. But brother can reverse-engineer and disassemble it, which shows that your skills are much higher than mine.
I have also learned a lot from brother and other friends these days in the forum. Because I have been on business trips recently and was busy with some year-end affairs, I haven't been able to surf the Internet for some days. Finally, I'm done. I'm going back to my hometown to celebrate the Spring Festival tomorrow, and I'll have more than half a month without the Internet again. I wish the friends in the forum a happy Chinese New Year!
|

☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
|
|
2006-1-22 00:58 |
|
|
willsort
元老会员
         Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
Re bush:
这段代码确实只能在 NT 系列系统中使用,而且如在签名中提示的一样,仅在 “开始-运行” 对话框中使用。至于它是否能在非 XP 的2K和2K3中使用,未经现场测试不敢妄断。
Re 无奈何:
这篇文章断断续续花了三天的工夫才最终完稿,有些技巧也是亲自测试后才更有体会的,所以学业高低不能一概而论,兄不必自谦。
其它回复请见原稿“后序”。下为我编写的通用文本渐次显示的试验代码。存在许多不足,比如不能处理空行,不能正确处理文本行中的转义字符( " % 等)。张贴于下,有心人可以继续研究。
@echo off & setlocal EnableDelayedExpansion
for /f "delims=" %%l in (%1) do (
set line=%%l
for /l %%i in (0,1,80) do (
set /p=!line:~%%i,1!<nul
ping/n 1 127.1>nul
)
echo.
)
pause
Last edited by willsort on 2006-1-22 at 14:09 ]
Re bush:
This code can indeed only be used in NT series systems, and as indicated in the signature, it is only used in the "Start - Run" dialog box. As for whether it can be used in non - XP 2K and 2K3, I can't arbitrarily judge without on - site testing.
Re 无奈何:
This article was finally completed after three days of intermittent work. Some techniques are only more experienced after personal testing, so academic levels can't be generalized, brother, there's no need to be modest.
For other replies, please see the "Postscript" of the original manuscript. The following is the test code I wrote for the gradual display of general text. There are many deficiencies, such as not being able to handle blank lines and not being able to correctly handle escape characters ("% and so on) in text lines. It is posted below, and those who are interested can continue to study.
@echo off & setlocal EnableDelayedExpansion
for /f "delims=" %%l in (%1) do (
set line=%%l
for /l %%i in (0,1,80) do (
set /p=!line:~%%i,1!<nul
ping/n 1 127.1>nul
)
echo.
)
pause
Last edited by willsort on 2006-1-22 at 14:09 ]
|

※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-1-22 10:44 |
|
|
chenall
银牌会员
    
积分 1276
发帖 469
注册 2002-12-23 来自 福建泉州
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
修改了一下,可以正常显示一些像"="之类的字符,解决了一行只能80个字符的限制
可以达到最多9999个(没有测试过,不知一行是否可以有9999个字符)
一行完就直接跳到下一行,不需要等待
@echo off & setlocal EnableDelayedExpansion
for /f "delims=" %%l in (%1) do (
set line=%%l
call :show
echo.
)
pause
goto end
:show
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto end
set /p= !line:~%%i,1!<nul
ping/n 1 127.1>nul
)
:end
Modified to display characters like "=" normally and solved the limit of only 80 characters per line. It can reach up to 9999 characters (not tested to see if a line can have 9999 characters). When a line is done, it directly jumps to the next line without waiting
@echo off & setlocal EnableDelayedExpansion
for /f "delims=" %%l in (%1) do (
set line=%%l
call :show
echo.
)
pause
goto end
:show
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto end
set /p= !line:~%%i,1!<nul
ping/n 1 127.1>nul
)
:end
|

QQ:366840202
http://chenall.net |
|
2006-3-10 10:44 |
|
|
chenall
银牌会员
    
积分 1276
发帖 469
注册 2002-12-23 来自 福建泉州
状态 离线
|
『第 6 楼』:
使用 LLM 解释/回答一下
另外一个版本(有声版,每显示一个字就"嘟"一下)
@echo off & setlocal EnableDelayedExpansion
for /f "delims=" %%l in (%1) do (
set line=%%l
call :show
echo.
)
pause
goto end
:show
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto end
set /p=!line:~%%i,1!<nul
)
:end
Another version (audio version, each time a character is displayed, there is a "beep" sound)
@echo off & setlocal EnableDelayedExpansion
for /f "delims=" %%l in (%1) do (
set line=%%l
call :show
echo.
)
pause
goto end
:show
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto end
set /p=!line:~%%i,1!<nul
)
:end
|

QQ:366840202
http://chenall.net |
|
2006-3-10 10:48 |
|
|
chenall
银牌会员
    
积分 1276
发帖 469
注册 2002-12-23 来自 福建泉州
状态 离线
|
『第 7 楼』:
使用 LLM 解释/回答一下
由于set /p=!line:~%%i,1!<nul
里面的可以让PC喇叭响一下"嘟"声.并且有延迟效果,所以就不需要使用PING来延迟了.
注:我的系统是2003的,以上程序在我的系统中测试正常.
以上的两个版本均无法正常显示"!","^"和空行
其它的字符均可以(我试了键盘上所有可以按出来的字符).只有"!"和"^"不能显示.
Last edited by chenall on 2006-3-10 at 11:19 ]
Because of set /p=!line:~%%i,1!<nul
The in it can make the PC speaker ring a "beep" sound and has a delay effect, so there is no need to use PING for delay.
Note: My system is 2003, and the above program tested normally in my system.
The above two versions cannot normally display "!", "^" and blank lines
Other characters are all okay (I tried all the characters that can be typed on the keyboard). Only "!" and "^" cannot be displayed.
Last edited by chenall on 2006-3-10 at 11:19 ]
|

QQ:366840202
http://chenall.net |
|
2006-3-10 10:51 |
|
|
chenall
银牌会员
    
积分 1276
发帖 469
注册 2002-12-23 来自 福建泉州
状态 离线
|
『第 8 楼』:
使用 LLM 解释/回答一下
经过测试,
终于解决了不能显示"!","^"的问题!
新的代码如下.
现在基本上可以算是完美的了.只差一个无法处理空行的问题了.
稍微解释一下.
可以显示特殊字符主要是这一句
set /p= !line:~%%i,1!<nul
是退格符(删除前一个字符)(ASCII码08)
所以在前面多放了一个空格.如果不加这个空格就会变成显示一个字符就删除一个字符.
另外就是在读取出来的每一行后面加了一个用来判断每一行结束的字符.
@echo off
for /f "delims=" %%l in (%1) do (
set line=%%l
call :show
echo.
)
pause
goto end
:show
setlocal EnableDelayedExpansion
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto end
set /p= !line:~%%i,1!<nul
ping/n 1 127.1>nul
)
:end
我用来显示的文件内容
`1234567890-=\
~!@#$%^&*()_+|
qwertyuiop
QWERTYUIOP{}
asdfghjkl;'
ASDFGHJKL:"
zxcvbnm,./
ZXCVBNM<>?
""""""""""
!!!!!!!!!!
^^^^^^^^^^
&&&&&&&&&&
Last edited by chenall on 2006-3-10 at 11:41 ]
After testing, the problem of not being able to display "!" and "^" is finally solved! The new code is as follows. Now it can basically be considered perfect. The only problem is the inability to handle blank lines.
A brief explanation. The main reason for being able to display special characters is this line: set /p= !line:~%%i,1!<nul. is the backspace character (deletes the previous character) (ASCII code 08). So a space is added in front. If this space is not added, it will become that one character is displayed and then deleted. In addition, a character used to judge the end of each line is added after each line read out.
@echo off
for /f "delims=" %%l in (%1) do (
set line=%%l
call :show
echo.
)
pause
goto end
:show
setlocal EnableDelayedExpansion
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto end
set /p= !line:~%%i,1!<nul
ping/n 1 127.1>nul
)
:end
The content of the file I used for display
`1234567890-=\
~!@#$%^&*()_+|
qwertyuiop
QWERTYUIOP{}
asdfghjkl;'
ASDFGHJKL:"
zxcvbnm,./
ZXCVBNM<>?
""""""""""
!!!!!!!!!!
^^^^^^^^^^
&&&&&&&&&&
Last edited by chenall on 2006-3-10 at 11:41 ]
|

QQ:366840202
http://chenall.net |
|
2006-3-10 11:16 |
|
|
maya0su
中级用户
  
积分 241
发帖 131
注册 2005-9-28
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
原来在这儿,终于找到了,我还以为willsort兄跟无奈何兄没兴趣做这点儿事!经过弟我的测试chenall兄的代码更好一些,在此写过以上各位,willsort兄又给我上了一课,太精彩了,已收藏,谢谢!
So it's here. Finally found it. I thought Brother willsort and Brother Wuna iHe had no interest in doing this little thing! After my test, Brother chenall's code is better. Here I write to the above各位, Brother willsort has taught me another lesson, it's wonderful, I've saved it, thank you!
(注:原文中“无奈何兄”翻译为“Brother Wuna iHe”可能不太准确,不过按照要求尽量保留原意翻译,另外“以上各位”翻译为“the above各位”不太符合英语表达习惯,可能是原文输入有误,这里先按原文大致翻译,若有更准确的理解可进一步调整,但整体先按要求处理。)
|

房东说:这娃是个好孩子! |
|
2006-3-21 17:27 |
|
|
doscc
中级用户
  
积分 256
发帖 93
注册 2006-3-26 来自 广东
状态 离线
|
|
2006-3-27 22:42 |
|
|
IceCrack
中级用户
   DOS之友
积分 332
发帖 168
注册 2005-10-6 来自 天涯
状态 离线
|
『第 11 楼』:
使用 LLM 解释/回答一下
哎.没有想到一个签名还能引出来这么大的学问啊.真的不简单
Hey. Didn't expect a signature could bring out so much knowledge. Really not simple
|

测试环境: windows xp pro sp2 高手是这样炼成的:C:\WINDOWS\Help\ntcmds.chm |
|
2006-7-29 02:56 |
|
|
electronixtar
铂金会员
      
积分 7493
发帖 2672
注册 2005-9-2
状态 离线
|
『第 12 楼』:
使用 LLM 解释/回答一下
一个签名引起的麻烦
Troubles caused by a signature
|

C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>" |
|
2006-7-29 14:49 |
|
|
my3439955
中级用户
  
积分 272
发帖 99
注册 2006-6-2
状态 离线
|
『第 13 楼』:
使用 LLM 解释/回答一下
8楼的代码好棒
但是“只差一个无法处理空行的问题了”
这不能不说是一个遗憾
小弟略加修改
成一续貂之作
@echo off
type %1 | find "" /V /N | findstr "^\*\]$" >C:\_tmp_.txt
set /A "turn=1"
for /f "usebackq delims=" %%l in (%1) do (
call :space
set line=%%l
if "%line%"=="" (
echo.
) else (
call :show
)
echo.
set /A "turn+=1"
)
del C:\_tmp_.txt
pause
goto :EOF
:show
setlocal EnableDelayedExpansion
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto :EOF
set /p= !line:~%%i,1!<nul
ping/n 1 127.1>nul
)
goto :EOF
:space
:begin
type C:\_tmp_.txt | find "">nul && (
echo.
set /A "turn+=1"
goto :begin
)
goto :EOF
借用八楼的测试文件:
`1234567890-=\
~!@#$%^&*()_+|
qwertyuiop
QWERTYUIOP{}
asdfghjkl;'
ASDFGHJKL:"
zxcvbnm,./
ZXCVBNM<>?
""""""""""
!!!!!!!!!!
^^^^^^^^^^
&&&&&&&&&&
Last edited by my3439955 on 2006-10-19 at 01:14 ]
The code> in floor 8 is great. But "just one problem of not being able to handle empty lines is left" This has to be said to be a pity. Little brother made a little modification and made a follow - up work.
@echo off
type %1 | find "" /V /N | findstr "^\*\]$" >C:\_tmp_.txt
set /A "turn=1"
for /f "usebackq delims=" %%l in (%1) do (
call :space
set line=%%l
if "%line%"=="" (
echo.
) else (
call :show
)
echo.
set /A "turn+=1"
)
del C:\_tmp_.txt
pause
goto :EOF
:show
setlocal EnableDelayedExpansion
for /l %%i in (0,1,9999) do (
if "!line:~%%i,1!"=="" goto :EOF
set /p= !line:~%%i,1!<nul
ping/n 1 127.1>nul
)
goto :EOF
:space
:begin
type C:\_tmp_.txt | find "">nul && (
echo.
set /A "turn+=1"
goto :begin
)
goto :EOF
Borrow the test file of floor 8:
`1234567890-=\
~!@#$%^&*()_+|
qwertyuiop
QWERTYUIOP{}
asdfghjkl;'
ASDFGHJKL:"
zxcvbnm,./
ZXCVBNM<>?
""""""""""
!!!!!!!!!!
^^^^^^^^^^
&&&&&&&&&&
Last edited by my3439955 on 2006-10-19 at 01:14 ]
|

X5O!P%@AP |
|
2006-10-19 01:01 |
|
|
yfd11
初级用户
 
积分 44
发帖 15
注册 2006-10-18
状态 离线
|
『第 14 楼』:
使用 LLM 解释/回答一下
,@call,set/p= %,:~%i,1%<nul
老大这部分不懂啊.为什么加,号.就是%,:~%i,1%为什么不输出变量","的所有内容呢?
,@call,set/p= %,:~%i,1%<nul
Boss, I don't understand this part. Why add the comma. That is, why doesn't %,:~%i,1% output all the content of the variable ","?
|
|
2006-10-19 10:29 |
|
|
NaturalJ0
银牌会员
    
积分 1181
发帖 533
注册 2006-8-14
状态 离线
|
『第 15 楼』:
使用 LLM 解释/回答一下
好复杂,以前就自己看过这段签名,看不懂@_@,今天看了这段分析总算懂了。^_^
It's so complicated. I just read this signature before and didn't understand it @_@. Today after reading this analysis, I finally understand. ^_^
|
|
2006-10-19 22:12 |
|
|