cmd批处理转义字符%的详细解释

cmd批处理转义字符%的详细解释

在命令行中使用for时不需要双%,这源于命令解释器对命令行与批处理的处理方式不同。

1、%是个ESCAPE字符,通常将之译为转义字符,但也有更形象的译名脱逸字符、逃逸字符等。也就是说%不仅仅将与其相关的特定字符串转义并替换为特定字符串,而且自身也会被“脱逸”。而且类似于C语言中的转义字符"\",双%会转义并脱逸为单%,四%则脱为双%。

2、for本身是一个特殊的命令,类似于一个特化的命令解释器,因为它的功能实现需要执行多条语句,因此它必须也具有对命令行(特指do后的命令行)分析处理的功能。而command/cmd实现for时自然会借用自身原有的命令行分析模块,因此for具有二级转义的特性,for中do后的语句被分两级分析和解释,第一级在command/cmd读入并解释for命令行时,第二级在for读入并解释do命令时,它通常会对同一命令行的进行多次解释。

然后,我们可以注意到,在do中使用命令行参数变量和环境变量时,不需要双%,那是因为,这些变量在经过第一级转义后,被替换成特定的不变的字符串常量,参与for循环的所有执行过程;而替代变量则要求在执行(do后的子命令行中)过程中不断的动态变化,而这个变化自然仍需要通过脱逸字符来实现,因此使用双%就是成了必然的选择。

另外,还需要注意到,在命令行中使用for时不需要双%,这源于命令解释器对命令行与批处理的处理方式不同。在早期的DOS版本中,%在命令行中不被视为转义字符,所以不会被转义和脱逸,所以当时无法在命令行直接引用环境变量。而使用for时,只需要一个%供for进行转义和脱逸就够了。在以后的命令解释器版本中,加入了命令行转义的支持(主要是环境变量的支持),但命令行for使用单%的传统仍然保留了下来。

而 cmd中的变量延迟替换是属于特殊的情况,但不违背以上的转义原则,只是for中的环境变量不再是常量了。

案例:

我在自己的一个bat文件,内容:

@echo off

if "%1" == "" (goto input_data) ELSE (goto input_var)

:input_data

set /p var=INPUT DATE(fmt:yyyyMMddHHmm):

goto start

:input_var

set /a var=%1

goto start

:start

cd  %cd%

md ..\..\to-save\TKcard\%var%

mysql -P3302 -uroot -pdst72j$mq)c%%8 -h61.160.245.119 -N -s -e"SET SESSION group_concat_max_len = 99999999;SELECT CONCAT(‘mysqldump -h61.160.245.119 -P3302 -uroot

-pdst72j$mq)c%%%%8 --opt -n TKCard_cn_cn_db210060000 ‘,GROUP_CONCAT(t.TABLE_NAME SEPARATOR  ‘ ‘),‘ >‘) FROM information_schema.TABLES t WHERE t.TABLE_SCHEMA =

‘TKCard_cn_cn_db210060000‘ AND (t.TABLE_NAME LIKE ‘dict_%%‘)  AND t.TABLE_NAME NOT IN(‘dict_keyvalue‘,‘dict_server‘,‘dict_operator_config‘);" > tkcard_dict.bat

for /f "delims=] tokens=1" %%a in (tkcard_dict.bat) do echo %%a ..\..\to-save\TKcard\%var%\tkcard_dict.sql >tkcard_dict.bat

call tkcard_dict.bat

上边功能是将远程指定数据库中的所有基础数据导出来。文件中写了一个mysql 连接数据库的脚本,并且在这个脚本里 通过“-e” 参数执行 导出所有基础表数据的脚本代码(即mysqldump 命令),结果没有达到自己的预期效果,分析原因,操作内网数据库就可以,把ip地址改为远程数据库地址就不行了,分析来分析去最后原来是这个 数据库连接密码问题,即密码内网密码没有 特殊字符 % ,而远程的这个有%,结果就是这个% 没有特殊转义出的问题,上边的脚步里涉及2处相同的密码,一处是 连接数据库时要密码,还一个是 对数据库中导出所有基础数据时用的 mysqldump命令时也要再要一次相同的密码,这个bat文件一共2处密码,而且都是一样的,密码里又涉及%,结果我就是没有对这2处% 进行特殊转义出问题了。上边的是已经正确转义了,原来密码为:  dst72j$mq)c%8   ,  第一处正确转义是在%前再加一个%,第二处是需要%前加3个%。 由于文章开头%转义规则,2个%转义一次为%,4个%转义后为2个%,那这里第一处要想正确连接数据库就保证密码为原始密码即有自身的一个%,那就必须加一个%,那这样第一处密码里就有2个%,当windows 的命令行 解释器执行连接数据库时会转义这2个% 为一个%,刚好和原始密码一样,而上边第二处密码要想也保证和原始密码一样那也要多加%,至于加几个,我们先来看看上边第二处涉及的逻辑先理一下。上边一个是连接数据库,并且后缀mysql 的参数命令-e 即 执行后边的sql脚本,即先连接数据库然后执行后边脚本,结构为 mysql  -P[大写p为端口]  -u[连接数据库的账号]  -p[小写p为连接数据库的密码]  -h[数据库ip地址]  -N[不显示列信息]   -s[一行一行输出,中间有tab分隔]   -e[执行mysql的sql语句,后跟双引号,双引号里为sql脚本代码]"[双引号里为前边-e后跟的sql脚本-此省略下边解释]"    >tkcard_dict.bat[上边sql执行的结果定向到tkcard_dict.bat文件中,由于tkcard_dict.bat前没有路径,那就是当前目录,如果没有tkcard_dict.bat文件就创建,有就覆盖]    for...[for循环开始执行tkcard_dict.bat文件]。

这里特别把上边-e后的双引号中的脚本拿出来解释: SET SESSION group_concat_max_len = 99999999;SELECT CONCAT(‘mysqldump -h61.160.245.119 -P3302 -uroot

-pdst72j$mq)c%%%%8 --opt -n TKCard_cn_cn_db210060000 ‘,GROUP_CONCAT(t.TABLE_NAME SEPARATOR  ‘ ‘),‘ >‘) FROM information_schema.TABLES t WHERE t.TABLE_SCHEMA =

‘TKCard_cn_cn_db210060000‘ AND (t.TABLE_NAME LIKE ‘dict_%%‘)  AND t.TABLE_NAME NOT IN(‘dict_keyvalue‘,‘dict_server‘,‘dict_operator_config‘);"

意思是先设置grop_concat函数本次查询session的长度,然后 select  concat(mysqldump代码-是把代码拼成字符串常量此不会执行  ,   group_concat(把从information_schema.TABLES 表中按照where条件全查出来的dict基础表名字查出来用一个空格间隔并且拼成一个字符串)-整个group_concat 的结果作为前边concat函数的一个参数     ,   ‘ >‘  )

可以看出-e后双引号中的脚步 中那个 select 脚步功能主要就是 从 information_schema.TABLES(这个数据库中的TABLES表中存放是这台mysql服务器中除了information_schema外的所有其他数据库名字,以及所有数据库中所有表名字,具体点即TABLES表中TABLE_SCHEMA字段存放是数据库名字,TABLES表中TABLE_NAME字段存放是每个数据库中表的名字) 表中按照where条件中给定的数据库名字和数据表名字2个条件查询出基础数据表的表名字,然后把查出的基础数据表名字通过GROUP_CONCAT 函数用一个空格间隔并且拼成一个字符串,然后再和 mysqldump命令的字符串 以及 一个‘[有一个空格] >‘  共三个参数 通过concat 函数 拼成一个最终的字符串 ,然互通过“ > tkcard_dict.bat ” 重定向到 tkcard_dict.bat文件中,即 tkcard_dict.bat文件中内容最终 是 :      mysqldump  -h61.160.245.119 -P3302 -uroot

-pdst72j$mq)c%%%%8 --opt -n TKCard_cn_cn_db210060000   基础表1  基础表2   基础表3  ...  >

至于for 后边的代码就是不太清楚了,估计就是执行上边 新生成的 tkcard_dict.bat 文件中的内容吧,而其内容刚好就是 一个mysqldump脚本,所以就把这个mysqldump脚本执行后的结果都导入到  自定路径下的tkcard_dict.sql 文件中把。至于最后的最上边bat代码中的最后的那个 “>tkcard_dict.bat” 就不知道干什么用的了。

时间: 03-06

cmd批处理转义字符%的详细解释的相关文章

CMD批处理——forfiles命令使用,自动删除过期备份文件

公司服务器用来备份数据的硬盘过段时间就会被备份文件占满,弄得我老是要登录到服务器去手工删除那些老的文件,有时忘记了就会导致硬盘空间不足而无法备份.因为只要保留最近几天的备份,如果可以做一个批处理让系统自动删除老备份文件就好了,但是Windows的命令行和Linux的Shell比起来功能差了很多,到底行不行我自己也不清楚.于是上网查了一下各位大虾发的帖子,再经过自己的摸索和尝试,发现只要花点功夫还是能实现这个功能的.Windows Server 2003内置的命令行文件,适合于XP以上系统示例:

445port入侵详细解释

445port入侵详细解释   大约"445port入侵"内容445port入侵详细解释网站搜索许多其他的"445port入侵"内容 445port入侵,以前我们先来看看或445port早干嘛去了,成为侵入port呢?445port就是IPC 服务的默认port                                                            ipc$一 摘要 二 什么是 ipc$ 三 什么是空会话 四 空会话能够做什么 五 ip

C语言scanf函数详细解释(转)

函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]); scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息.可以读入任何固有类型的数据并自动把数值变换成适当的机内格式. 其调用格式为:      scanf("<格式化字符串>",<地址表>); scanf()函数返回成功赋值的数据项数,出错时则返回EOF. 其控制串由三类字符构成: 1.格式化说明

Android中多线程编程(四)AsyncTask类的详细解释(附源码)

Android中多线程编程中AsyncTask类的详细解释 1.Android单线程模型 2.耗时操作放在非主线程中执行 Android主线程和子线程之间的通信封装类:AsyncTask类 1.子线程中更新UI 2.封装.简化异步操作. 3.AsyncTask机制:底层是通过线程池来工作的,当一个线程没有执行完毕,后边的线程是无法执行的.必须等前边的线程执行完毕后,后边的线程才能执行. AsyncTask类使用注意事项: 1.在UI线程中创建AsyncTask的实例 2.必须在UI线程中调用As

我对CONTAINING_RECORD宏的详细解释

宏CONTAINING_RECORD的用处其实还是相当大的, 而且很是方便, 它的主要作用是: 根据结构体中的某成员的指针来推算出该结构体的指针! 下面从一个简单的例子开始说起: 我们定义一个结构体, 同时类型化: typedef struct{ int a; int b; int c; }ss; 这是一个很简单的结构体, 没什么特殊的, 稍微分析下该结构体: 结构体的大小(字节):4+4+4=12字节 成员a的偏移:0 成员b的偏移:4 成员c的偏移:8 我们用ss来定义一个变量: ss s

Atitit&#160;.jvm&#160;虚拟机指令详细解释

Atitit .jvm 虚拟机指令详细解释 1. 一.未归类系列A1 2. 数据mov系列2 2.1. 二.const系列2 2.2. 三.push系列2 2.3. ldc系列 该系列命令负责把数值常量或String常量值从常量池中推送至栈顶.3 2.4. 5.1.load系列A 该系列命令负责把本地变量的送到栈顶.3 2.5. 5.2.load系列B 该系列命令负责把数组的某项送到栈顶.4 2.6. 6.1.store系列A 该系列命令负责把栈顶的值存入本地变量.5 2.7. 6.2.stor

Sed命令的使用详细解释

Sed命令的使用详细解释 一:sed命令的简介 sed是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕.接着处理下一行,这样不断重复,直到文件末尾.文件内容并没有改变,除非你使用重定向存储输出.Sed主要用来自动编辑一个或多个文件:简化对文件的反复操作:编写转换程序等.     二:Sed的用法格式 Sed [options] 'scri

设计模式 - 迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释

迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考迭代器模式(iterator pattern): http://blog.csdn.net/caroline_wendy/article/details/35254643 Java的标准库(util)中包括迭代器接口(iterator interface), import java.util.Iterator; 继承

C语言 - 结构体(struct)比特字段(:) 详细解释

结构体(struct)比特字段(:) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26722511 结构体(struct)能够使用位字段(:), 节省空间, 例如以下面代码, 结构体a中的, 第一个变量x占用1个字符, y占用2个字符, z占用33个字符(越界); 可是sizeof()会自己主动补齐, 如x+y一共占用4个字节, z占用8个字节, 所以结构体占用12个字节; 当使用加法运算时, 会初始化为0; 代码