在For
命令语踞饽参数F中,最难理解的就是Delims
和Tokens
两个选项,本文简单的做一个比较和总拮。
“For /f
”常用来解析文本,读取字符串。分工上,delims
负责切分字符串,而tokens
负责提取字符串。如果把字符串当作蛋糕,Delims
像刀子,用来切蛋糕,tokens
像叉子,用来取切好的蛋糕。下面我们用实例来进行理解。
把以下内容保存为文本文件“歌曲列表.txt
”,注意扩展名为“.txt
”:
序号、歌手名-歌曲名.后缀名
1、饶天亮-玫瑰爱人.wma
2、高一首-我不愿错过.mp3
3、黃凱芹-傷感的戀人.MP3
4、黄灿-黄玫瑰.lrc
5、黎姿-如此这般的爱情故事.mp3
代码1:显示全部内容
@echo off
for /f %%i in (歌曲列表.txt) do echo %%i
pause>nul
运行拮果:
序号、歌手名-歌曲名.后缀名
1、饶天亮-玫瑰爱人.wma
2、高一首-我不愿错过.mp3
3、黃凱芹-傷感的戀人.MP3
4、黄灿-黄玫瑰.lrc
5、黎姿-如此这般的爱情故事.mp3
讲解:
如果不使用参数“/f
”,运行结果只显示括号里的文字字符“歌曲列表.txt
”,而不能读取文本文件“歌曲列表.txt”中的内容。可见,“/f”是解析文本字符串的好工具。
一、delims
假如只要序号,不要歌手名、歌曲名和后缀名,如何办到?
代码2:默认提取第一列
@echo off
for /f "delims=、" %%i in (歌曲列表.txt) do echo %%i
pause>nul
运行拮果:
序号
1
2
3
4
5
讲解:
"delims=、
"表示定义顿号“、
”为分隔符,并用该分隔符“、
”切分文本字符串。字符串就是“歌曲列表.txt
”里的内容,也就是文件里的文字和标点符号。
该顿号是原文中就有的。除了顿号“、
”,原文中还有减号“-
”和点号“.
”,因此你也可以用它们来做分隔符。
代码3:用减号“-”做分隔符
@echo off
for /f "delims=-" %%i in (歌曲列表.txt) do echo %%i
pause>nul
运行拮果:
序号、歌手名
1、饶天亮
2、高一首
3、黃凱芹
4、黄灿
5、黎姿
讲解:
因为,当减号“-
”被用做分隔符时,每行内容被减号“-
”分隔成前后两半,默认只显示前半部分,而后半部分连同分隔符减号“-
”都被忽略(省略)了。
代码4:用点号“.
”做分隔符
@echo off
for /f "delims=." %%i in (歌曲列表.txt) do echo %%i
pause>nul
运行拮果:
序号、歌手名-歌曲名
1、饶天亮-玫瑰爱人
2、高一首-我不愿错过
3、黃凱芹-傷感的戀人
4、黄灿-黄玫瑰
5、黎姿-如此这般的爱情故事
讲解:
默认情况下,单纯使用delims
而不用tokens
时,只显示第一个分隔符前的内容,第一个分隔符和第一个分隔符后面的内容将被忽略。
代码5:定义多个分隔符
@echo off
for /f "delims=、-." %%i in (歌曲列表.txt) do echo %%i
pause>nul
运行拮果:
序号
1
2
3
4
5
讲解:
原因是,当定义顿号“、
”、减号“-
”和点号“.
”三个标点符号为分隔符后,原文被分隔成四个部分。
如第二行“1、饶天亮-玫瑰爱人.wma
”将被分隔成“1
”、“饶天亮
”、“玫瑰爱人
”和“wma
” 四个部分。
从第一行到最后一行,每行的每个部分对应下来相当于一个竖列。因此,原文就有“序号”、“歌手名”、“歌曲名”、“后缀名”四列。
一般情况下,只读取第一列的内容。后面的内容需要用tokens
选项提取。
二、tokens
假如只要歌手名和歌曲名,不要序号和后缀名,如何办到?
代码6:提取单列
@echo off
for /f "tokens=2 delims=、." %%i in (歌曲列表.txt) do echo %%i
pause>nul
运行拮果将显示:
歌手名-歌曲名
饶天亮-玫瑰爱人
高一首-我不愿错过
黃凱芹-傷感的戀人
黄灿-黄玫瑰
黎姿-如此这般的爱情故事
讲解:
用delims
定义顿号“、
”和点号“.
”作为分隔符,将原文分成三部分。
如第六行“5、黎姿-如此这般的爱情故事.mp3
”被分割成:
第一部分(第一列):5
第二部分(第二列):黎姿-如此这般的爱情故事
第三部分(第三列):mp3
“tokens=2
”表示用tokens
提取第二列的字符串,即“黎姿-如此这般的爱情故事
”。
没有被tokens
定义提取的第一列和第三列将被忽略。
假如只要序号和歌曲名,而不要歌手名和后缀名,如何办到?
代码7:提取多列
Rem 更改活动控制台代码页编码
chcp 65001>nul
@echo off
for /f "tokens=1,3 delims=、-." %%i in (歌曲列表.txt) do echo %%i %%j
pause>nul
运行拮果将显示:
序号 歌曲名
1 玫瑰爱人
2 我不愿错过
3 傷感的戀人
4 黄玫瑰
5 如此这般的爱情故事
讲解:
“delims=、-.
”表示定义顿号、减号和点号为分隔符。
“tokens=1,3
”表示只提取第一列和第三列。
“%%i %%j
”对应于“token”后面的列数。有多少列就要有多少个输出变量,并且各变量中的字母存在先后顺序。
如何只提取文字,不要标点符号?
代码8:忽略分隔符
@echo off
for /f "tokens=12-4 delims=、-." %%i in (歌曲列表.txt) do echo %%i %%j %%k %%l
pause>nul
运行拮果:
序号 歌手名 歌曲名 后缀名
1 饶天亮 玫瑰爱人 wma
2 高一首 我不愿错过 mp3
3 黃凱芹 傷感的戀人 MP3
4 黄灿 黄玫瑰 lrc
5 黎姿 如此这般的爱情故事 mp3
讲解:
默认情况下,用做分隔符的标点符号将被忽略。
“tokens=12-4
”中的“2-4
”表示第二至第四列。
三、小结
“For /f
”
一句话总拮:解析文本,读取字符串。
Delims
的语法:
FOR/F "Delims=符号集" %%I
IN(Command1)DO
Command2
一句话总拮:忽略分隔符,切分字符串。
delims
的意义包括两个方面:
第一、指定原文中的标点符号作为分隔符。使得文本被划分为许多小部分,方便使用批处理命令读取和编辑。
第二、读取第一个分隔符之前的内容。忽略第一个分隔符和分隔符后面的内容,如需读取和编辑,需要使用tokens
等命令。
注意分隔符和标点符号的联系和区别。
分隔符就是原文中的标点符号,可以是一个标点符号也可以是多个。但原文中的标点符号不一定是分隔符。
分隔符需要定义,即用”delims=
”来指定,等于号后面跟被用来做分隔符的标点符号,该标点符号来自原文。
当有多个标点符号被定义为分隔符时,标点符号之间没有空格。当用空格做分隔符时,空格应该放在其它用作分隔符的标点符号之后。
即使不使用delims
,默认情况下,批处理也将空格作为分隔符。如文件名“Program Files
”中含有空格时,批处理一般只读取空格前的“Program
”,剩下的“Files
”被忽略了。
例:
代码9:空格默认作为分隔符
@echo off
for /f "delims=" %%a in ("伟大的中国人民万岁 万岁 万万岁") do echo %%a
pause>nul
运行拮果:
伟大的中国人民万岁 万岁 万万岁
讲解:
“delims=
”代表取消默认以空格作为分隔符。
批处理默认空格是分隔符,分隔符会隐藏第一个分隔符后面的所有内容。为了显示完整的信息,所以有必要取消该功能。
因此,当文件名或路径中含有空格时,需要用双引号括住。如果不使用双引号,括号内的内容将被当做文件名,如果文件名不存在,将提示“系统找不到……
”。
如果不使用“delims=
”,即使使用双引号,也只能显示第一个空格前面的字符串,后面的字符串将被默认忽略。
Tokens
的语法:
FOR/F "tokens=xym-n" %%I IN(Command1)DOCommand2
一句话总拮:提取列。
Tokens
的意义就是,提取指定的列。
注意列与踞饽联系与区别。
文本内容由许多文字字符串组成,它们被标点符号分隔,两个标点符号之坚饽语句我们称为“句子”。
当标点符号被“tokens=
”指定为分隔符之后,文字将被分成多个部分。对应的每行的每个部分我们称之为“列”。
一列可能是一个句子,也可能包含多个句子,视delims
定义的标点符号而定。
其它方面:关于“行”的提取,前面做过一个很简单的:
@echo off
findstr /n .* 12.txt>>122.txt
set /p m=请输入要定位的行:
findstr /b "%m%" 122.txt
pause
批处理之 for /f
中的delims
和tokens
0x00 前言
今天在对windows进行提权之前的系统信息收集的时候,需要使用到一条批处理语句把特定部分的内容从一个txt的文本当中提取出来;该条语句是如下:
for /f "tokens=2,3 delims==" %%a in (tmplist.txt) do (echo %%a >> software.txt)
当时跟着流程操作的时候,对这条语句的了解也只是仅限于知道这条语句的作用是将tmplist.txt
文本文件里面的内容按照一定规则取出想要的部分的内容输出到software.txt
文本里;
但是跟着教程一路操作下来,到了这一步却出现了如下的错误:
报出的错误是此处不应有%%a
,按照这个错误提示去搜索,也没有找到一个能解决的答案
反复确认前面的操作也一模一样过后,到了我这里却不对了,这种感觉是很不爽的,所以需要弄明白这条指令的确切使用方法与含义。
0x01 对整条语句的分解剖析
1、for /f
:用来解析文本,读取字符串 ,将要读取的文本就是tmplist.txt
。
2、tokens
:tokens
负责提取字符串。具体用法见实例。
3、delims
:根据定义的符号,负责切分字符串,比如delims==
就是根据=
号来切分字符串。
4、in 、do
:也就是表面的含义吧,在什么里面和做什么
5、(tmplist.txt
):要操作的文本文件
6、echo %%a >> software.txt
: 将一段内容重定向到software.txt
文本中
0x02 示例1
要处理的文本文件名为:tmplist.txt
,其内容为:
1、饶天亮=玫瑰爱人.wma
2、高一首=我不愿错过.mp3
3、黃凱芹=傷感的戀人.MP3
4、黄灿=黄玫瑰.lrc
5、黎姿=如此这般的爱情故事.mp3
–显示文本文件内的全部内容,执行的命令:
for /f %%i in (tmplist.txt) do echo %%i
得到的结果如下:
0x03 示例2
–假如只要序号和歌手名,不要歌曲名和后缀名(默认提取左边的内容),执行的命令:
for /f "delims==" %%a in (tmplist.txt) do echo %%a
得到的结果如下:
delims
的作用就是设定分割符,"delims==
"表示定义等号“=
”为分隔符,并用该分隔符“=
”切分文本字符串。字符串就是“tmplist.txt
”里的内容,也就是文件里的文字和标点符号。
0x04 示例4
–假如只要歌手名和歌曲名,不要序号和后缀名,执行的命令如下
for /f "tokens=2 delims=*." %%a in (tmplist.txt) do echo %%a
经过实际的尝试,发现如果使用中文编码的符号顿号“、
”来作为分割符,是无法正确得到结果的,所以将序号后面的顿号全部改为“*
” ,以便测试的正常进行;
1*饶天亮=玫瑰爱人.wma
2*高一首=我不愿错过.mp3
3*黃凱芹=傷感的戀人.MP3
4*黄灿=黄玫瑰.lrc
5*黎姿=如此这般的爱情故事.mp3
得到的结果如下:
所以用delims
定义顿号“*
”和点号“.
”作为分隔符,将原文分成三部分。
例如:1*饶天亮=玫瑰爱人.wma
这一行就被分为以下三部分:
1
···················第一部分给定序号为1
饶天亮=玫瑰爱人
············第二部分给定序号为2
wma
··················第三部分给定序号为3
tokens
的意义就是,提取指定的列。
所以当内容被分为3部分过后,tokens
的作用就是根据他们各自的序号来选择取出那一部分的字符串用来输出,所以在刚才示例中tokens
的值为2
,因此表示的就是取出被分割出来的字符串里面的第二部分内容
所以如果想要取出第2、3部分的话,代码如下:
for /f "tokens=1,3 delims=*." %%a in (tmplist.txt) do echo %%a %%b
不知道有没有发现,当tokens
的参数有两个时,在命令的最后多了一个参数 %%b
“%%a %%b
”对应于“token
”后面的列数。有多少列就要有多少个输出变量,并且各变量中的字母存在先后顺序。
0x05 关于最开始的报错:“此处不应有%%a
”的解决办法
根绝前面的分析,整条命令的用法,以及各个参数的含义已经基本了解,并且根据操作都能正确的执行并得到结果,但是当我还是按照我最后的理解在cmd
命令行里面去执行的时候,依然爆出“此处不应有%%a
”的错误,最后发现,如果将所有的需要执行的命令都放在.bat
的脚本文件里去执行的话都不会有任何错误,但是如果将命令直接放到cmd
命令行执行的话,还是不能正确执行;
最后找到的解决办法就是:如果想要在cmd
命令行里面使for /f "tokens=2,3 delims==" %%a in (tmplist.txt) do (echo %%a >> software.txt)
语句生效执行的话,需要将%%a
换成%a
,就能正确执行了;
0x06 参考链接
http://blog.sina.com.cn/s/blog_4b795cc10100ez8d.html