天天看点

批处理命令--文件篇之findstr

作者:批处理进阶

#暑期创作大赛#

上篇我们学习了find这个命令,一起来回顾下:

find用途:

用来在某一个或多个文件中查找指定的字符串并显示包含指定字符串的行。

find参数格式:

FIND [/V] [/C] [/N] [/I] "string" [pathname(s)]

/V:显示不包含指定字符串的所有行。

/C:只显示包含指定字符串的行数。

/N:在指定字符串行前显示行号

/I:查找字符串不区分大小写

这篇我们学习find的增强版findstr ,参数功能更多,连名字也名副其实:find string,在文件中寻找字符串findstr。该命令也是一个外部命令,它的作用是使用常规表达式搜索文件中的文本模式,其用法用途类似于Linux下的grep命令,用于查找过滤指定字符串。EditPlus软件也有类似的功能,如果不习惯批处理,EditPIus是个不错的选择。

首先还是来看一下语法。

批处理命令--文件篇之findstr
批处理命令--文件篇之findstr

看起来好像很复杂的样子。不过不要担心,主要是一些参数和元字符(正则表达式)的学习。在学习之前,我们了解下前面提到的常规表达式。

常规表达式,是用于指定文本类型的符号,与精确的字符串相反,标记使用文字字符和元字符。

每个在常规的表达式语法中,没有特殊意义的字符,都是文字字符,与出现的该字符匹配。例如字母和数字是文字符号。

元字符是在常规表达式语法中具有特殊意义(操作符或分隔符)的符号,使用在正则表达式中。

也就是findstr支持两种模式,一种是字面上的文字模式,使用文字字符;一种是正则表达式,可接受一些有特殊意义的元字符符号。在两种模式下输出的结果及参数也不尽相同。

1.文字模式,也是普通的模式,需要加参数/l,使用文字搜索字符串,find用的就是这种模式,find也只有这种模式。

2.正则模式,findstr默认的模式,加不加/r其实findstr都表示开启了正则模式。

为了方便叙述,我们还是把参数介绍和元字符先贴出来吧。

参数介绍:

findstr [/b] [/e] [/l] [/r] [/s] [/i] [/x] [/v] [/n] [/m] [/o] [/p] [/offline] [/g:file] [/f:file]

[/c:string] [/d:dirlist] [/a:ColorAttribute] [strings] [[Drive:][Path] FileName [...]]

/b (begin,开头)

如果位于行的开头则匹配模式。

/e (end,结尾)

如果位于行的末尾则匹配模式。

/l (literal,文字)

使用文字搜索字符串。

/r (Regular Expressions,正则表达式)

使用搜索串作为常规表达式。Findstr 将所有元字符解释为常规表达式,除非使用了/l。

/s (subdirectory,子目录)

在当前目录和所有子目录中搜索匹配的文件

/i (ignore,忽略)

指定搜索不区分(忽略)大小写。

/x (exactly,精确地)

打印完全匹配的行。

/v (excusive,排外,不NOT)

只打印不包含匹配的行。

/n (number,号码)

在每个匹配的行之前打印行号。

/m (match,filename,匹配,文件名)

如果文件包含匹配项,仅打印该文件名。

/o (offset,偏移)

在每次匹配行之前打印查找偏移量。

跳过包含非可打印字符的文件。

/offline(offline,脱机)

利用脱机属性设置处理文件

/f:file (file,文件)

从指定文件中读取文件列表。

/c:string (consoles,控制台,specified指定的)

使用指定的文本作为文字搜索字符串。

/g:file(get,grep,得到,搜索)

从指定文件得到搜索字符串。

/d:dirlist(dirlist,目录列表)

搜索以逗号分隔的目录列表。

/a:ColorAttribute

使用两个十六进制数指定颜色属性。

strings (字符串)

指定要在 FileName中搜索的文本。

[Drive:][Path] FileName […]

指定要搜索的文件。

元字符介绍:

.通配符:任何字符

*重复:以前字符或类的零次或多次出现

^行位置:行的开始

$行位置:行的结尾

[class]字符类:集合中任何一个字符

[^class]反类:不在集合中的任何一个字符

[x-y]范围:指定范围内的任何字符

\x取消:元字符x的文字用途

\<xyz字位置:字首

xyz\>字位置:字尾

下面开始介绍

语法:

1.findstr 参数 字符串 文件名(含路径,相对或绝对),这个顺序不能变,不同于find的可变顺序。

2.findstr字符串没有加引号,是的,你没看错,表示什么呢,表示字符串可不加引号,也可用双引号括起来,也不同于find的必须加引号。

3.findstr的多个参数可连写,也可单写,如/ic:,/bi等,不同于find必须一个个的写出来(单写),如/i /v。

4.findstr字符串支持正则和通配,可多个,find不支持,只能是一个指定的字符串。

参数:

1.搜索的不同

a、有参没参大不同

findstr "hello there" x.y

在文件x.y中查找"hello"或"there"并显示出包含这些字符串的行

findstr /c:"hello there" x.y

在文件x.y中查找"hello there"并显示出包含这个字符串的行

注意:findstr的参数/c是指定字符串的意思,代表引号内的字符串匹配(含空格);find的参数/c是指定字符串的行数(有多少行)。

b、参数不同搜索迥异

假如cc.txt文件里有如下行

^happy

happy birthday

happy day

findstr /ln "^happy" cc.txt

显示第一行

findstr /n "^happy" cc.txt

显示第二、三行

findstr /rn "^happy" cc.txt

显示第二、三行

::可以看出第一个命令使用了文字模式,元字符失效,第二三个均是正则,findstr默认开了正则模式,因此第二三个是等价的。

2.打印完全匹配的行 /x

findstr /xn "day" cc.txt

显示第三行

3.递归查找 /s

也就是在目录及其子目录中搜索匹配的文件,如:

:: 搜索当前目录及子目录下所有的 .txt 文件,并查找还有 hello 字符串的行, 并显示行号

findstr /n /s "hello" *.txt

4.反向匹配 /v

findstr /v "hello" test.txt

5.忽略大小写 /i

findstr /i "Day#34; cc.txt

6.匹配仅打印文件名 /m

findstr /mi "\<Windows\>" *.*

元字符:

1.代表任何字符的通配符为.不是*。

*是重复符,在正则表达式中的作用,是表示左侧字符或者表达式的重复次数,*号表示重复的次数为零次或者多次。

.*代表任意字符串。

2.^的作用

a.代表行的位置:行的开始。如^a代表该行以a开始。

如果要搜索以 FOR 开头的行,可以使用以下命令:

findstr /b /r /c:^FOR *.txt

b.取反,反类,不在集合中的任何一个字符。如[^x-yX-Y]代表不是任何一个大小写字母。

如果要搜索包含数字 0 到 9 以外的任何字符的行,可以使用以下命令:

findstr /r /c:[^0-9] *.txt

在 findstr 中,^ 是一个元字符,表示行中的位置。如果 ^ 位于正则表达式的开头,它表示匹配行的开头。如果 ^ 位于方括号内,它表示反向类,即匹配不在方括号内的任何字符。

c.转义,如findstr用在for /f的in后括号里被单引号''括住时,管道符号|前的^就代表转义。for /f命令里的特殊字符(如|)要转义,如:

for /f "skip=1 tokens=1,3" %%i in ('query user ^| findstr /v /c:" Disc "') do (actions)

在批处理文件中,^ 是一个转义字符,用于表示紧跟其后的字符的字面意义,而不是特殊含义。

因此,这段代码里的^|表示一个普通的管道符号,而不是一个元字符。它用于将 query user 命令的输出传递给 findstr 命令,进行文本过滤。

如果不使用 ^ 进行转义,批处理文件会将 | 解释为一个命令分隔符,而不是一个管道符号。这样就会导致语法错误或意外的结果。

3.$:行位置:行的结尾,如前面提到的例子findstr /i "Day#34; cc.txt。

^和$符号的应用

^ 表示行首匹配,"^hero"仅匹配 "heroisme"中的第一个单词。

$ 表示行尾匹配,"hero#34;仅匹配 "iamthehero"中最后一个单词。

4.[]表示集合,字符集,[X-Y]表集合内的任何一个字符,X-Y表任何一个大写字母,另外还有[0-9]等,表示范围内的任意一个。如果前面有^存在,则取反,如[^class]就是[class]的反类。

5.字首与字尾,\<Windows与Windows\>

如前文的findstr /mi "\<Windows\>" *.*

findstr "\<echo" 123.txt

所有含有以echo为前缀的字符串的行,都匹配。

findstr "echo\>" 123.txt

所有含有以echo为后缀的字符串的行,都匹配。

findstr "\<end\>123.txt

这里是用来精确查找单词。查找单词end的行,因为\<xyz\>格式要查找的是单个英文单词。

6.\X,取消:元字符X的文字用途,如\^表示^符号本身,不代表文字开头。\.表示.而不是元字符含义的任何字符。

5和6里,可以把\当作转义符号。

特别地:

1."[.*]" 如果在字符集内插入通配符和重复符号将视为普通字符,没有通配和重复的含义。

2.要查找的字符串含有\时,可以用\\把\给转义(一个\用二个\\代替),如果目标字符串的\后面还有内容,则搜索字符串\除了要变成\\(本身的转义要求),还可以在它后面再加一个字符,如\\.

findstr "\.abc" 123.txt

在文件123.txt中查找可以匹配“.abc”字符串的行,这里\.是把.给转义了。

findstr "1\\" 123.txt

在文件123.txt中查找可以匹配“1\”字符串的行,这里\\是把\给转义了。

转义符 \

把表达式中的特殊字符(元字符)转化为普通字符。常见写法:

\.

\*

\\

\[

\]??

\-

3.搜索引号,一个双引号用两个双引号来包,如搜索"56"(含双引号),可写成"""56"""

批处理里的应用:

主要是搭配for使用,结合type,管道符|,重定向>,>>等使用。

@echo off&echo 稍候...

for /r "MT" %%i in (*.txt) do (

for /f "tokens=1* delims=:" %%i in ('findstr/n .* %%~si')do (

echo %%i |findstr "152")

)

上面主要是在文件里的每一行前加行号,.*代表任意字符串,我们之前提到过的。do括号里的findstr尽管前面有管道,但不需要再转义,我们在find章提到过。

findstr/n .* %%~si

继续阅读