前言
此答案中的许多信息都是基于在Vista机器上运行的实验收集的。除非另有明确说明,否则我尚未确认该信息是否适用于其他Windows版本。
FINDSTR输出
文档永远不会费心解释FINDSTR的输出。它暗示了印有匹配线的事实,仅此而已。
匹配行输出的格式如下:
文件名:lineNumber:lineOffset:文本
哪里
fileName: =包含匹配行的文件的名称。如果请求是显式的单个文件请求,或者搜索管道输入或重定向输入,则不打印文件名。打印时,fileName将始终包含提供的任何路径信息。如果使用该/S
选项,将添加其他路径信息。打印的路径总是相对于提供的路径,如果没有提供,则相对于当前目录。
注意-使用非标准(且文献记录不充分)通配符 <
和时,可以避免文件名前缀>
。这些通配符如何工作的确切规则可以在此处找到。最后,您可以看一下非标准通配符如何与FINDSTR一起使用的示例。
lineNumber: =匹配行的行号,以十进制值表示,其中1表示输入的第一行。仅/N
在指定了选项的情况下打印。
lineOffset: =匹配行开头的十进制字节偏移量,其中0表示第一行的第一个字符。仅/O
在指定了选项的情况下打印。这不是行内匹配的偏移量。它是从文件开头到行开头的字节数。
text =匹配行的二进制表示形式,包括任何<CR>和/或<LF>。二进制输出不遗余力,因此与所有行匹配的此示例将生成原始文件的精确二进制副本。
FINDSTR "^" FILE >FILE_COPY
/ A选项设置仅输出fileName:,lineNumber:和lineOffset:的颜色。匹配行的文本始终以当前控制台颜色输出。/ A选项仅在将输出直接显示到控制台时才有效。如果将输出重定向到文件或通过管道传输,则/ A选项无效。请参阅Aacini答案中的2018-08-18编辑,以获取有关将输出重定向到CON时的越野车行为的描述。
在XP
上,大多数控制字符和许多扩展的ASCII字符都显示为点。XP上的FINDSTR在屏幕上将匹配行中的大多数不可打印的控制字符显示为点(句点)。以下控制字符是例外;它们将自己显示:0x09制表符,0x0A LineFeed,0x0B垂直制表符,0x0C换页,0x0D回车。
XP FINDSTR还将许多扩展的ASCII字符转换为点。在XP上显示为点的扩展ASCII字符与在命令行上提供时进行转换的扩展ASCII字符相同。请参阅本文后面的“命令行参数的字符限制-扩展ASCII转换”部分
如果输出通过管道传输,重定向到文件或在FOR IN()子句中,则控制字符和扩展ASCII不会在XP上转换为点。
Vista和Windows 7始终将所有字符显示为自己,而不是点。
返回码(ERRORLEVEL)
- 0(成功)
- 1(失败)
- 在任何文件的任何行中都找不到匹配项。
/A:xx
选项指定的颜色无效
- 2(错误)
- 不兼容的选项,
/L
并且/R
都指定
- 缺少参数后
/A:
,/F:
,/C:
,/D:
,或者/G:
- 由指定文件
/F:file
或/G:file
找不到文件
- 255(错误)
要搜索的数据源 (基于Windows 7的测试进行了更新)
Findstr只能从以下来源之一搜索数据:
参数/选项优先于重定向,重定向优先于管道数据。
文件名参数,/F:file
可以组合使用。可以使用多个文件名参数。如果/F:file
指定了多个选项,则仅使用最后一个。文件名参数中允许使用通配符,但不能在指向的文件中使用通配符/F:file
。
搜索字符串的来源 (更新基于Windows 7的测试)
的/G:file
和/C:string
选项可以组合。/C:string
可以指定多个选项。如果/G:file
指定了多个选项,则仅使用最后一个。如果使用/G:file
或/C:string
,则假定所有非选项参数都是要搜索的文件。如果/G:file
未/C:string
使用或未使用,则第一个非选项参数将被视为以空格分隔的搜索词列表。
使用该/F:FILE
选项时,文件名中不能包含引号。
文件名可能包含空格和其他特殊字符。大多数命令都要求使用此类文件名。但是FINDSTR /F:files.txt
选项要求不能在files.txt中引用文件名。如果使用引号将找不到该文件。
/D
/S
BUG- 短8.3文件名可能会破坏和选项与所有Windows命令一样,FINDSTR在查找要搜索的文件时将尝试同时匹配长名和短8.3名。假设当前文件夹包含以下非空文件:
b1.txt
b.txt2
c.txt
以下命令将成功找到所有3个文件:
findstr /m "^" *.txt
b.txt2
匹配,因为相应的短名称B9F64~1.TXT
匹配。这与所有其他Windows命令的行为一致。
但是带有/D
和/S
选项的错误导致以下命令只能找到b1.txt
findstr /m /d:. "^" *.txt
findstr /m /s "^" *.txt
该错误会阻止在同一目录b.txt2
中找到所有排序后的文件名以及所有文件名b.txt2
。找到其他之前排序的文件,例如a.txt
。d.txt
触发错误后,以后会丢失其他排序文件,例如。
搜索的每个目录均被独立对待。例如,该/S
选项将在未能在父文件夹中找到文件后成功开始在子文件夹中搜索,但是一旦该错误导致子文件夹中缺少简短的文件名,则该子文件夹中的所有后续文件也将被丢失。 。
如果在禁用了NTFS 8.3名称生成的计算机上创建了相同的文件名,则该命令将无错误运行。当然b.txt2
不会找到,但是c.txt
会正确找到。
并非所有的短名称都触发该错误。我见过的所有错误行为实例都涉及一个扩展名,该扩展名超过3个字符,且带有一个简短的8.3名称,该名称以与不需要8.3名称的普通名称相同的开头。
该错误已在XP,Vista和Windows 7上得到确认。
不可打印字符和/P
选项
该/P
选项使FINDSTR跳过包含以下任何十进制字节码的任何文件:0-7、14-25、27-31
。
换句话说,该/P
选项将仅跳过包含不可打印控制字符的文件。控制字符是小于或等于31(0x1F)的代码。FINDSTR将以下控制字符视为可打印的:
8 0x08 backspace
9 0x09 horizontal tab
10 0x0A line feed
11 0x0B vertical tab
12 0x0C form feed
13 0x0D carriage return
26 0x1A substitute (end of text)
所有其他控制字符都被视为不可打印字符,如果存在则导致/P
选择跳过文件。
可能已<CR><LF>
添加
了管道输入和重定向输入如果输入是管道输入,而流的最后一个字符不是<LF>
,则FINDSTR将自动追加<CR><LF>
到输入。在XP,Vista和Windows 7上已经确认了这一点。(我以前认为Windows管道负责修改输入,但是后来我发现FINDSTR实际上在进行修改。)
Vista上的重定向输入也是如此。如果用作重定向输入的文件的最后一个字符不是<LF>
,则FINDSTR将自动追加<CR><LF>
到输入。但是,XP和Windows 7不会更改重定向的输入。
在XP和Windows 7 FINDSTR挂起如果重定向输入不是结束<LF>
这是XP和Windows 7讨厌的“功能”如果一个文件的最后一个字符作为重定向输入不是结束<LF>
,然后FINDSTR将无限期挂起,一旦它到达重定向文件的末尾。
如果管道数据
的最后一行由单个字符组成<LF>
,则可以忽略该管道的最后一行。如果输入被管道输入并且最后一行由单个字符组成,且后面没有,则FINDSTR会完全忽略最后一行。
示例-第一个具有单个字符且没有no的命令<LF>
无法匹配,但是第二个具有2个字符的命令也可以正常工作,第三个具有一个字符并以换行符结尾的命令也可以正常工作。
> set /p "=x" <nul | findstr "^"
> set /p "=xx" <nul | findstr "^"
xx
> echo x| findstr "^"
x
由DosTips用户Sponge Belly报道在新的findstr错误中。在XP,Windows 7和Windows 8上得到确认。尚未听说过Vista。(我不再需要测试Vista)。
选项语法
选项可以使用/
或作为前缀,或者-
选项可以在单个/
或之后连接-
。但是,串联选项列表最多可以包含一个多字符选项,例如OFF或F :,并且多字符选项必须是列表中的最后一个选项。
以下是表示以任何顺序包含“ hello”和“再见”的任何行的不区分大小写的正则表达式搜索的所有等效方法
/i /r /c:"hello.*goodbye" /c:"goodbye.*hello"
-i -r -c:"hello.*goodbye" /c:"goodbye.*hello"
/irc:"hello.*goodbye" /c:"goodbye.*hello"
搜索字符串的长度限制
在Vista上,单个搜索字符串的最大允许长度为511字节。如果任何搜索字符串超过511,则结果为FINDSTR: Search string too long.
ERRORLEVEL 2(错误级别2)。
在执行正则表达式搜索时,最大搜索字符串长度为254。长度在255到511之间的正则表达式将导致FINDSTR: Out of memory
ERRORLEVEL 2 FINDSTR: Search string too long.
错误。正则表达式长度大于511会导致错误。
在Windows XP上,搜索字符串的长度显然较短。Findstr错误:“搜索字符串太长”:如何在“ for”循环中提取和匹配子字符串?
文字搜索和正则表达式搜索的XP限制均为127个字节。
行长限制
指定为命令行参数或通过/ F:FILE选项指定的文件没有已知的行长限制。已成功对不包含单个<LF>的128MB文件运行搜索。
管道数据和重定向的输入每行限制为8191字节。此限制是FINDSTR的“功能”。它不是管道或重定向所固有的。使用重定向的stdin或管道输入的FINDSTR将永远不匹配任何> = 8k字节的行。> = 8k的行将向stderr生成一条错误消息,但是如果在至少一个文件的至少一行中找到了搜索字符串,则ERRORLEVEL仍为0。
默认搜索类型:文字与正则表达式
/C:"string"
-默认为/ L文字。明确地将/ L选项与/ C组合在一起:“字符串”当然可以,但是很多余。
"string argument"
-默认值取决于第一个搜索字符串的内容。(请记住,<space>用于定界搜索字符串。)如果第一个搜索字符串是有效的正则表达式,其中包含至少一个未转义的元字符,则所有搜索字符串均被视为正则表达式。否则,所有搜索字符串均视为文字。例如,"51.4 200"
将被视为两个正则表达式,因为第一个字符串包含未转义的点,而"200 51.4"
将被视为两个文字,因为第一个字符串不包含任何元字符。
/G:file
-默认值取决于文件中第一个非空行的内容。如果第一个搜索字符串是一个有效的正则表达式,其中包含至少一个未转义的元字符,则所有搜索字符串都将被视为正则表达式。否则,所有搜索字符串均视为文字。
建议- 使用或时始终明确指定/L
文字选项或/R
正则表达式选项。"string argument"
/G:file
BUG-指定多个文字搜索字符串可能会导致结果不可靠
以下简单的FINDSTR示例即使找到了匹配项也无法找到匹配项。
echo ffffaaa|findstr /l "ffffaaa faffaffddd"
此错误已在Windows Server 2003,Windows XP,Vista和Windows 7上得到确认。
根据实验,如果满足以下所有条件,则FINDSTR可能会失败:
- 搜索使用多个文字搜索字符串
- 搜索字符串的长度不同
- 较短的搜索字符串与较长的搜索字符串有一定程度的重叠
- 搜索区分大小写(无
/I
选择)
在我看到的每一次失败中,它始终是较短的搜索字符串之一,它失败了。
有关更多信息,请参见为什么这个带有多个文字搜索字符串的FINDSTR示例找不到匹配项?
命令行参数中的引号和反斜杠
注- 用户MC ND的注释反映了此部分的实际复杂的规则。涉及3个不同的解析阶段:
- 首先,cmd.exe可能需要将某些引号转为^“(与FINDSTR无关)
- 接下来的FINDSTR使用2008年以前的MS C / C ++参数解析器,该解析器对“和\”具有特殊的规则。
- 参数解析器完成后,FINDSTR还将\后面跟一个字母数字字符视为文字,但将\后面跟一个非字母数字字符视为转义字符。
此突出显示部分的其余部分不是100%正确。它可以作为许多情况的指南,但是要完全理解,需要上述规则。
在命令行搜索字符串中转义引号命令行搜索字符串中的
引号必须使用反斜杠()进行转义
\"
。对于文字和正则表达式搜索字符串都是如此。此信息已在XP,Vista和Windows 7上得到确认。
注意:对于CMD.EXE解析器,可能还需要转引号,但这与FINDSTR无关。例如,要搜索单引号,可以使用:
FINDSTR \^" file && echo found || echo not found
在命令行文字搜索字符串中转义反斜杠文字搜索字符串中的
反斜杠通常可以表示为
\
或\\
。它们通常是等效的。(在Vista中可能有不寻常的情况,必须始终转义反斜杠,但我不再需要测试Vista机器)。
但是有一些特殊情况:
搜索连续的反斜杠时,除最后一个之外的所有反斜杠都必须转义。最后的反斜杠可以有选择地转义。
\\
可以编码为\\\
或\\\\
\\\
可以编码为\\\\\
或\\\\\\
在引号之前搜索一个或多个反斜杠很奇怪。逻辑建议必须将引号转义,并且每个前导反斜杠都必须转义,但这是行不通的!相反,每个前导反斜杠必须双转义,并且引号通常转义:
\"
必须编码为 \\\\\"
\\"
必须编码为 \\\\\\\\\"
如前所述,^
对于CMD解析器,一个或多个转义引号也可能需要转义。
此部分中的信息已在XP和Windows 7上得到确认。
在命令行正则表达式搜索字符串中转义反斜杠
仅适用于Vista:正则表达式中的反斜杠必须\\\\
在字符类集中(例如)必须是两次转义,例如,或者是单个转义
[\\]
XP和Windows 7:正则表达式中的反斜杠始终可以表示为[\\]
。通常可以表示为\\
。但是,如果反斜杠在转义的引号之前,则这将永远无效。
转义引号之前的一个或多个反斜杠必须被双转义,或者编码为 [\\]
\"
可能被编码为\\\\\"
或[\\]\"
\\"
可能被编码为\\\\\\\\\"
or [\\][\\]\"
或\\[\\]\"
在/ G:FILE文字搜索字符串中
转义引号和反斜杠不必转义/ G:file指定的文字搜索字符串文件中的单引号和反斜杠,但可以转义。
"
和\"
等价。
\
和\\
等价。
如果要查找\\,则必须至少转义前导反斜杠。双方\\\
和\\\\
工作。
如果目的是要找到\”,那么至少领先的反斜杠必须进行转义,两者\\"
和\\\"
工作。
在/ G:FILE regex搜索字符串中转义引号和反斜杠
这是一种情况,根据文档,转义序列可以按预期工作。Quote不是正则表达式的元字符,因此不必转义(但可以转义)。反斜杠是正则表达式的元字符,因此必须转义。
命令行参数的字符限制-扩展ASCII转换
命令行上的任何字符串中都不能出现空字符(0x00)。任何其他单字节字符都可以出现在字符串(0x01-0xFF)中。但是,FINDSTR会将在命令行参数中找到的许多扩展ASCII字符转换为其他字符。这从两个方面产生重大影响:
1)如果在命令行中用作搜索字符串,许多扩展的ASCII字符将不匹配。对于文字和正则表达式搜索,此限制是相同的。如果搜索字符串必须包含扩展ASCII,/G:FILE
则应改用该选项。
2)如果名称包含扩展的ASCII字符并且在命令行上指定了文件名,则FINDSTR可能找不到文件。如果要搜索的文件名称中包含扩展ASCII,/F:FILE
则应改用该选项。
这是FINDSTR对命令行字符串执行的扩展ASCII字符转换的完整列表。每个字符都表示为十进制字节代码值。第一个代码表示命令行中提供的字符,第二个代码表示其转换为的字符。注意-此列表是在美国计算机上编译的。我不知道其他语言可能对该列表产生什么影响。
158 treated as 080 199 treated as 221 226 treated as 071
169 treated as 170 200 treated as 043 227 treated as 112
176 treated as 221 201 treated as 043 228 treated as 083
177 treated as 221 202 treated as 045 229 treated as 115
178 treated as 221 203 treated as 045 231 treated as 116
179 treated as 221 204 treated as 221 232 treated as 070
180 treated as 221 205 treated as 045 233 treated as 084
181 treated as 221 206 treated as 043 234 treated as 079
182 treated as 221 207 treated as 045 235 treated as 100
183 treated as 043 208 treated as 045 236 treated as 056
184 treated as 043 209 treated as 045 237 treated as 102
185 treated as 221 210 treated as 045 238 treated as 101
186 treated as 221 211 treated as 043 239 treated as 110
187 treated as 043 212 treated as 043 240 treated as 061
188 treated as 043 213 treated as 043 242 treated as 061
189 treated as 043 214 treated as 043 243 treated as 061
190 treated as 043 215 treated as 043 244 treated as 040
191 treated as 043 216 treated as 043 245 treated as 041
192 treated as 043 217 treated as 043 247 treated as 126
193 treated as 045 218 treated as 043 249 treated as 250
194 treated as 045 219 treated as 221 251 treated as 118
195 treated as 043 220 treated as 095 252 treated as 110
196 treated as 045 222 treated as 221 254 treated as 221
197 treated as 043 223 treated as 095
198 treated as 221 224 treated as 097
不在上面列表中的任何> 0字符都将被视为自身,包括<CR>
和< LF>
。包括<CR>
和这样的奇数字符的最简单方法<LF>
是将它们放入环境变量中,并在命令行参数中使用延迟扩展。
在/ G:FILE和/ F:FILE选项指定的文件中找到的字符串的字符数限制
nul(0x00)字符可以出现在文件中,但其功能类似于C字符串终止符。nul字符之后的所有字符都被视为不同的字符串,就像它们在另一行一样。
的<CR>
和<LF>
字符都被视为行结束终止的字符串,并且不包括字符串英寸
所有其他单字节字符都完美地包含在字符串中。
搜索Unicode文件
FINDSTR无法正确搜索大多数Unicode(UTF-16,UTF-16LE,UTF-16BE,UTF-32),因为它无法搜索nul字节,并且Unicode通常包含许多nul字节。
但是,TYPE命令将带BOM的UTF-16LE转换为单字节字符集,因此,以下命令将与带BOM的UTF-16LE一起使用。
type unicode.txt|findstr "search"
请注意,活动代码页不支持的Unicode代码点将转换为?
字符。
只要您的搜索字符串仅包含ASCII,就可以搜索UTF-8。但是,控制台输出的任何多字节UTF-8字符都不正确。但是,如果将输出重定向到文件,则结果将被正确编码为UTF-8。请注意,如果UTF-8文件包含BOM表,则BOM表将被视为第一行的一部分,这可能会引发与行首匹配的搜索。
如果将搜索字符串放入UTF-8编码的搜索文件(无BOM)中,并使用/ G选项,则可以搜索多字节UTF-8字符。
行尾
FINDSTR在每个<LF>之后立即中断行。<CR>的存在或不存在对换行符没有影响。
跨换行符搜索
正如预期的那样,.
正则表达式元字符将不匹配<CR>或<LF>。但是可以使用命令行搜索字符串在换行符中进行搜索。<CR>和<LF>字符必须明确匹配。如果找到多行匹配项,则仅打印匹配项的第一行。然后,FINDSTR加倍返回源中的第二行,并再次开始搜索-一种“向前看”类型的功能。
假设TEXT.TXT具有这些内容(可以是Unix或Windows风格)
A
A
A
B
A
A
然后这个脚本
@echo off
setlocal
::Define LF variable containing a linefeed (0x0A)
set LF=^
::Above 2 blank lines are critical - do not remove
::Define CR variable containing a carriage return (0x0D)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
setlocal enableDelayedExpansion
::regex "!CR!*!LF!" will match both Unix and Windows style End-Of-Line
findstr /n /r /c:"A!CR!*!LF!A" TEST.TXT
给出这些结果
1:A
2:A
5:A
使用/ G:FILE选项搜索换行符是不精确的,因为匹配<CR>或<LF>的唯一方法是通过将EOL字符夹在中间的正则表达式字符类范围表达式。
[<TAB>-<0x0B>]
匹配<LF>,但也匹配<TAB>和<0x0B>
[<0x0C>-!]
匹配<CR>,但也匹配<0x0C>和!
注意-上面是正则表达式字节流的符号表示,因为我无法以图形方式表示字符。
答案在下面的第2部分中继续...
grep
,这是非常容易理解和记录的:-) 例如,请参见stackoverflow.com/questions/2635740/…。