批处理中的预处理实现代码_DOS/BAT

转载自 nxhujiee最终编辑 LJ_SunTB批处理中的【预处理】
━━━━━━━━━━━━━━━━━━━━━━━━━━

如果你对脱字字符“^”的处理机制比较熟悉那么可以接着阅读,否
则请先参考脱字字符的相关文章。

一、预处理究竟要做什么?

根据我的经验,预处理要做的是变量值的替换和特殊符号的处理。究竟先执行哪个操作呢,我认为要先进行变量值的替换。理由有三:

1、 从逻辑上看

set var=2&echo %var%
类似于这样的语句,如果说先进行特殊符号处理的话,势必要先处理符号“&”,而“&”是用来连接两条命令的,这样一来该行就理所应当的被理解为两句,那么我们还要变量延迟干嘛。这里应该是
先对变量var赋值,然后处理特殊符号“&”。

2、从运行结果看

复制代码 代码如下:

@echo off
set var=^^^>
echo %var%
pause

这句“set var=^^^>”首先也会被预处理,预处理之后var的值为“^>”。
本例的输出结果是“>”,因此可以证明系统先将变量的值替换为“^>”然后再处理特殊符号“^”。

3、从变量替换上看

复制代码 代码如下:

@echo off
set ^&var=hero
echo %&var%
pause

结果:显示“hero”
这也说明变量的替换先于特殊符号的处理。

二、启动了变量延迟之后预处理又是如何进行呢?

我的看法是这样的:如果语句中存在英文叹号“!”则会被预处理两次,其它情况仍然是预处理一次。由于脱字字符比较特殊,因此在此借助该符号写几个例子说明一下。

(一)

复制代码 代码如下:

@echo off
echo !^^^^^>
setlocal enabledelayedexpansion
echo !^^^^^>
pause

两个echo语句的结果不同。下面做一下分析:
对于第一个echo语句,变量延迟没有开启,进行预处理的时候该句就被预处理为“echo !^^>”,这也就是输出的结果。由此可见预处理只进行了一次。

对于第二个echo语句,此时变量延迟开启,由于有“!”存在,首先进行一次预处理得到“echo !^^>”,再进行一次得到“echo ^>”,结果也是如此。
之所以没有输出叹号,是因为开启了变量延迟,叹号就变为了特殊符号。

(二)

复制代码 代码如下:

@echo off
setlocal enabledelayedexpansion
set var=hero
echo !var!
pause

像这里的“echo !var!”不是没有被预处理,而是被预处理了两次。看下面的这段代码就可以理解了。

复制代码 代码如下:

@echo off
setlocal enabledelayedexpansion
set var=hero
echo !var!^^^^^>
pause

运行的结果为:“hero^>”。我们来分析一下,进行第一次预处理时,由于“!var!”,因此先不替换变量值而进行特殊符号的处理,处理完后就成了“echo !var!^^>”;之后再进行一次预处理,
此时就要替换“!var!”了,处理完后就成了“echo hero^>”。

(三)
我们再来看看当变量延迟开启时语句中不存在英文叹号的情况。

复制代码 代码如下:

@echo off
echo ^^^^^>
setlocal enabledelayedexpansion
echo ^^^^^>
pause

@echo off
set var=hero
echo %var%^^^^^>
setlocal enabledelayedexpansion
echo %var%^^^^^>
pause

怎么样,也就是说如果没有“!”就不会进行第二次处理。

(四)
对于!!型,特殊符号的处理是在变量替换之前进行的。

例、

复制代码 代码如下:

@echo off
setlocal enabledelayedexpansion
set ^&var=hero
echo !&var!
pause

这段代码运行结果是错误的。

例、

复制代码 代码如下:

@echo off
setlocal enabledelayedexpansion
set var=^&
echo !var!
pause

这段代码运行结果是正确的。

(五)
既然都要处理符号,那么%%型和!!型的符号处理会不会是同一个过程?

(一)中的例子已经可以说明问题,不过我还有例子可以证明。

例、

复制代码 代码如下:

@echo off
echo "^^^^^^^^"!!
setlocal enabledelayedexpansion
echo "^^^^^^^^"!!
pause

对于%%型,在符号处理时,不处理双引号间的脱字字符;而对于!!型则相反。

三、call引出的一些问题

(一)
call与脱字字符

例、

复制代码 代码如下:

@echo off
set /p var=<hero.txt
echo "%var%"
call echo "%var%"
pause

其中hero.txt中的内容为8个脱字字符:^^^^^^^^

结果是:
"^^^^^^^^"
"^^^^^^^^^^^^^^^^"
请按任意键继续. . .

结果是否有些出乎意料?我们知道,系统在预处理时不会处理双引号间的脱字字符,那就意味着是call命令将其后的脱字字符数量加了倍。看来call命令和脱字字符还真有点“暧昧”。

例、

复制代码 代码如下:

@echo off
set /p var=<hero.txt
echo %var%
call echo %var%
pause

本例中变量var的值为8个“^”,运行“call echo %var%”时,首先进行变量替换把%var%替换为^^^^^^^^,再经一次符号的处理变为^^^^,此时由于call命令使得脱字字符数目增加一倍变为8个,然后再进行
call本身的预处理,这样结果就为4个“^”。

这样就能解释下面的代码为什么会显示4个“^”。

复制代码 代码如下:

@echo off
call call call call echo ^^^^^^^^
pause

(二)
call与其它特殊字符
这里所说的“其它特殊字符”主要指&、>、|等。

这里请允许我自定义两个名词:
主预处理过程:系统本身预处理过程的总称,其中包括了%%型和!!型。
次预处理过程:由于call命令引起的预处理过程的总称。
“其它特殊字符”是在主预处理过程中被系统识别的,而在次预处理
过程中对这些符号的识别是有问题的。

例、

复制代码 代码如下:

@echo off
call echo hero!^&pause
pause

本例中,经过主预处理过程,&被识别为普通字符,而在次预处理过程中符号&的识别将产生问题。正如《命令行参考》中提到的--不要在call 命令中使用管道和重定向符号。(这倒不是说call语句中不能使
用那些符号,而是这些符号不能作为参数传递给call命令。)

这也从某种程度上说明某行语句的句子结构(一条还是多条)和功能(是从定向输出还是其它)是在主预处理过程中确定的。

以上所有内容,只是我个人的看法,由于没有官方文档的支持,因此仅供参考。

那么我们学了以上种种内容又有什么实际用途呢?我想,懂得了以上道理就可以写出更加个性化的代码,同时也可以作为一种伪装术在实际中应用。

复制代码 代码如下:

@echo off
set ^&=setlocal enabledelayedexpansion
set ^^^^^hero=^^^^^&p
set ^au=^^^au
set ^^^^^^^^^=障眼法
%&%
set ^^^^^se=^^^se!
echo %^^^^%!%^^hero%!au%^se%

怎么样,这段代码能看明白吗?

时间: 2024-10-24 12:17:18

批处理中的预处理实现代码_DOS/BAT的相关文章

让批处理被wsh解析的代码_DOS/BAT

示例批处理:test.bat  复制代码 代码如下: :On Error Resume Next   Sub bat   echo off & cls   echo Batching_codez_here_following_vbs_rules & pause   start wscript -e:vbs "%~f0"   Exit Sub   End Sub   MsgBox "This is vbs"    上面的代码巧妙利用 bat 和 vbs

使用BAT批处理执行sql语句的代码_DOS/BAT

1.把待执行Sql保存在一个文件,这里为20110224.sql.2.新建一个扩展名.bat的批处理文件,输入下面命令并保存后,双击.bat文件,系统会自动执行20110224.sql的语句: 复制代码 代码如下: osql -S gdjlc -d TestDB -U sa -P 1 -i 20110224.sql osql参数见下面=======================================================================: E:\>osql

批处理中实现替换文本内容_DOS/BAT

首先: 注册表添加一个或两个 REG_DWORD 值: HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\EnableExtensions 或 HKEY_CURRENT_USER\Software\Microsoft\Command Processor\EnableExtensions 设值为1 新建文件aaa.bat: @echo off set f=c:\aaa.txt set f2="c:\aaa.bak.txt" f

批处理程序中的“多线程”处理代码_DOS/BAT

如下内容将简单举例,在WINDOWS下使用批处理做多进程并发,以达到"多线程"的效果. 例:需要PING 192.168.0.1到192.168.0.254的所有IP地址,并将是否能PING通的结果输出到log.txt 实现如下: rem 主程序.bat,只需一行代码,调用checkip.bat,经测试,CPU2.6G MEM1G可并发40个左右的进程 复制代码 代码如下: for /l %%i in (1,1,254) do (start /min cmd /c checkip.ba

用批处理设置IP安全策略的代码_DOS/BAT

以下内容只有回复后才可以浏览 ipseccmd -w REG -p "XIAOWANG" -r "Block ICMP" -f *+0:ICMP -n BLOCK -x 开网上邻居.bat 复制代码 代码如下: ipseccmd -w REG -p "XIAOWANG" -r "Block TCP/80" -f *+0:80:TCP -n PASS -x ipseccmd -w REG -p "XIAOWANG&qu

批处理随机取值练习代码_DOS/BAT

出题目的: 掌握利用random进行随机取值技巧 解题要求: 代码通用.高效 尽量简洁 尽量不生成临时文件 加分规则: 1 思路独特基准分5分 2 代码高效.通用基准分4分 3 技巧高超基准分3分 4 代码简洁基准分2分 5 完美代码加分15分 题目如下: 已知有1-26与a-z的一一对应,如1对应a 10对应j 26对应z,要求用批处理 从1-26 a-z这52个值中(全视为值)随机抽取10个互不相同的值并显示出来, 注意如同1和a 24和x 26和z这样的取值均视为相同不合要求. 解题限制:

批处理中常用的符号总结_DOS/BAT

^ 转义符   用在特殊符号之前 比如: echo 非常^&批处理 如果不加^ 那么"批处理"将被当作命令执行 | (管道)传递符 当然是传递作用 比如: echo 0123456 | find "123"  将0123456 传递给find 查找 123 || 连接符 当前面的命令没有成功执行 则执行后面的命令 比如: echo 0123456 | find "789" || echo 字符中没有789 &&  连接符

批处理解约瑟夫环应用题代码_DOS/BAT

题目: 有二十九个女生(分别用1-29号来称呼)围成一圈玩报数游戏,规则是这样的:从1开始数数,当数到3的这个人就退出游戏,而她后面的人接着从1数...如此一直到最后剩下一个人,现在知道最初是从13号女生开始的游戏,问最后剩下的会是第几号女生? 要求: 1 用批处理解答 2 代码简洁高效 3 代码通用且不生成临时文件 加分原则: 以思路为重(如思路独特,请简要说明) 完全符合要求的加10分 已有两套解决方案,见3楼more和6楼ieutk版主的代码,但个人认为这两套方案均不完美(见本人的跟贴评述

批处理写的电视机效果代码_DOS/BAT

  复制代码 代码如下: @echo off   title 收不到台的电视机  :a  cls  for /l %%b in (1,6,7)do (  color %%bf  )  goto a