假设有文件内容如下,其以列表形式显示了不同文件夹中文件数量,要求提取清单列中最后一列的数字。
CHECK IS THERE ANY INTERFACE FILES IN I/O DIRS ------------------------------------------------------------------------------- 08 JUN 18 16:40:24 FILES IN ..\BNK.DATA\OFSDATA\AIO.IN.DIR: 0 FILES IN AIO.IN.FILE: 0 FILES IN F.AIOCARD.CREDIT.OUT: 0 FILES IN ..\BNK.DATA\OFSDATA\RTGS.IN.DIR: 0 FILES IN RTGS.IN.FILE: 0 FILES IN RTGS.OUT.FILE: 0 FILES IN ..\BNK.DATA\OFSDATA\RTGS.OUT.DIR: 0 FILES IN OFS.IN: 0 FILES IN SWIFT.FTP\F.DE.I.MS000: 0 FILES IN SWIFT.FTP\F.DE.O.MS000: 93类似于此类(文件处理、字段抽取)问题,dos中提供功能强大的for语句进行处理。因而,处理思路如下:
1. 需要找到带文件个数的行,它们以FILES IN 开头,另外需要排除非FILES IN 开头的行;
2. 在1的基础上,对于每行文本,若以空格作为分割符,数字都处于第四列,因而需要想办法提取第四列内容。
1. setlocal enabledelayedexpansion
设置本地为延时扩展,其实也就是:延迟变量,全称延迟环境变量扩展。下面是dos官方解释(setlocal/?):
开始批处理文件中环境改动的本地化操作。在执行 SETLOCAL 之后所做的环境改动只限于批处理文件。要还原原先的设置,必须执行 ENDLOCAL。达到批处理文件结尾时,对于该批处理文件的每个尚未执行的 SETLOCAL 命令,都会有一个隐含的 ENDLOCAL 被执行。
2. cd %~dp0
进入脚本所在目录,脚本和待处理的文件(chkio_out.txt)放在同一目录
3. set FILENAME=%~dp0chkio_out.txt
拼接完整的待处理路径名;
4. for /f "delims=^" %%iin (%FILENAME%) do (
@echo %%i | findstr /B"FILES" >nul && (set str=%%i & (for /f "tokens=4delims= " %%m in ("!str!") do (
echo%%m)))
)
此双层for语句为文件处理主体,具体分析如下:
a. 外层for循环以^(换行符)作为分隔符,逐行读取文件内容;
b. @echo %%i | findstr /B"FILES" >nul
首先echo每行内容,再采用管道过滤以FILES开头的行,findstr的参数/B表示:在一行的开始配对模式,之后将结果重定到nul(不打印到屏幕)
c. set str=%%i & (for /f"tokens=4 delims= " %%m in ("!str!") do ( echo %%m)))
经过前一轮for处理,我们抽取出所有以FILES开头的行。此处再进行第二层处理,重新将每行内容赋予变量str(字符串),再对字符串进行字段分割:
tokens=4表示将分割产生的第四个字段传递到循环体;
delims= (注意等号后面有空格)表示以空格分割字符串
!str! 表示字符串内容,因为采用延时绑定,需要用!!取变量内容
echo %%m 最后echo出结果。
这种文件处理/字段分割的例子,首先要对照文件安内容设计清晰的处理思路,DOS中FOR命令是处理此类问题的能手,读者只要自己写几个,就能孰能生巧。
FOR
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] FOR /F ["options"] %variable IN ("string") DO command [command-parameters] FOR /F ["options"] %variable IN ('command') DO command [command-parameters] fileset 为一个或多个文件名。继续到 fileset 中的下一个文件之前, 每份文件都被打开、读取并经过处理。处理包括读取文件,将其分成一行行的文字, 然后将每行解析成零或更多的符号。然后用已找到的符号字符串变量值调用 For 循环。 以默认方式,/F 通过每个文件的每一行中分开的第一个空白符号。跳过空白行。 您可通过指定可选 "options" 参数替代默认解析操作。这个带引号的字符串包括一个 或多个指定不同解析选项的关键字。这些关键字为: eol=c - 指一个行注释字符的结尾(就一个) skip=n - 指在文件开始时忽略的行数。 delims=xxx - 指分隔符集。这个替换了空格和跳格键的 默认分隔符集。 tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代 的 for 本身。这会导致额外变量名称的分配。m-n 格式为一个范围。通过 nth 符号指定 mth。如果 符号字符串中的最后一个字符星号, 那么额外的变量将在最后一个符号解析之后 分配并接受行的保留文本。 usebackq - 指定新语法已在下类情况中使用: 在作为命令执行一个后引号的字符串并且一个单 引号字符为文字字符串命令并允许在 file-set 中使用双引号扩起文件名称。 findstr 在文件中寻找字符串。 FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P] [/F:file] [/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]] strings [[drive:][path]filename[ ...]] /B 在一行的开始配对模式。 /E 在一行的结尾配对模式。 /L 按字使用搜索字符串。