Windows FINDSTR命令的未记录功能和限制是什么?


188

Windows FINDSTR命令已被严格记录。通过FINDSTR /?或可以使用非常基本的命令行帮助HELP FINDSTR,但是这是远远不够的。在https://docs.microsoft.com/zh-cn/windows-server/administration/windows-commands/findstr上有更多在线文档。

文档中甚至没有暗示许多FINDSTR功能和限制。没有事先的知识和/或仔细的实验​​,也无法预料到它们。

因此,问题是- 未记录的FINDSTR有哪些功能和限制?

该问题的目的是提供许多未记录功能的一站式存储库,以便:

A)开发人员可以充分利用其中的功能。

B)开发人员不会浪费时间去思考为什么某些东西在看起来应该正确时不起作用。

在进行响应之前,请确保您了解现有文档。如果该信息包含在帮助中,则该信息不属于此处。

这也不是显示FINDSTR有趣用途的地方。如果有逻辑的人可以根据本文档来预期FINDSTR的特定用法的行为,那么它不属于此处。

同样,如果有逻辑的人可以根据任何现有答案中包含的信息来预测特定用法的行为,那么同样,它也不属于此处。


15
或者,您也可以完全放弃这个笨拙的未记录的MS实用程序,然后安装/使用grep,这非常容易理解和记录的:-) 例如,请参见stackoverflow.com/questions/2635740/…
paxdiablo 2012年

17
无论如何,如果您可以使用FINDSTR以外的其他方式,则强烈建议您这样做。但是有些人处于禁止第三方公用程序的环境中。
dbenham

4
没有冒犯。我认真考虑过要放入与您的评论相似的FINDSTR免责声明!:)
dbenham 2012年

41
我感到震惊和失望,有人会发现这个问题“不是建设性的”,并投票结束。为了避免出现“意见,辩论,论据,民意测验或扩大讨论范围”,很多问题专门针对该问题。该问题已发布3.5个月,而所引用的否定词均未发生。配对的答案充满了事实,需要花费大量时间进行艰苦的研究和实验。
dbenham

6
一些读者可能会对findstr命令的历史背景感兴趣:blogs.msdn.com/b/oldnewthing/archive/2012/11/28/10372436.aspx
哈里·约翰斯顿

Answers:


279

前言
此答案中的许多信息都是基于在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选项的文件名。

  • 通过重定向的标准输入 findstr "searchString" <file

  • 来自管道的数据流 type file | findstr "searchString"

参数/选项优先于重定向,重定向优先于管道数据。

文件名参数,/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.txtd.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 memoryERRORLEVEL 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部分中继续...


45
出色的完整性。如果只有互联网上的所有答案都是这样。
Mike Viens

1
我们遇到了addpath.bat来自Q141344和findstr 的问题,这可能与上述Win7挂起问题有关。我创建了一个聊天室,试图追踪下来,任何人谁是感兴趣:chat.stackoverflow.com/rooms/13177/...
马特·威尔基

2
编辑-在XP上将控制字符描述为点显示。还记录了错误/S/D从8.3短文件名衍生的选项。
dbenham

1
编辑-1)/ F:FILE指定的文件内的文件名不能用引号引起来。2)扩展ASCII字符的转换在命令行中提供时会同时影响搜索字符串和文件名。
dbenham

1
编辑-添加了以下错误:如果管道输入的最后一行包含单个字符而没有,则忽略该管道的最后一行<LF>
dbenham 2013年

64

答案从上面的第1部分继续 -我遇到了30,000个字符的答案限制:-(

有限的正则表达式(regex)支持
FINDSTR对正则表达式的支持非常有限。如果HELP文档中未包含该内容,则不支持。

除此之外,所支持的regex表达式是以完全非标准的方式实现的,因此结果可能与预期的结果不同,例如grep或perl。

正则表达式行位置锚点^和$
^匹配输入流的开始以及紧随<LF>之后的任何位置。由于FINDSTR还会在<LF>之后打断行,因此简单的正则表达式“ ^”将始终匹配文件(甚至二进制文件)中的所有行。

$与<CR>之前的任何位置匹配。这意味着包含的正则表达式搜索字符串$将永远不会匹配Unix样式文本文件中的任何行,如果缺少<CR> <LF>的EOL标记,它将不会与Windows文本文件的最后一行匹配。

注–如前所述,通过管道传输和重定向到FINDSTR的输入可能已经<CR><LF>附加了,但不在源中。显然,这会影响使用的正则表达式搜索$

与之前的任何字符搜索字符串^或之后$将永远无法找到一个匹配。

位置选项/ B / E / X
位置选项与^和相同$,但它们也适用于文字搜索字符串。

/ B的功能与^正则表达式搜索字符串开头的功能相同。

/ E的功能与$正则表达式搜索字符串末尾的功能相同。

/ X的功能^$在正则表达式搜索字符串的开头和结尾处具有相同的功能。

正则表达式单词边界
\<必须是正则表达式中的第一个术语。如果有其他字符,则该正则表达式将不匹配任何内容。\<对应于输入的开头,行的开头(紧随<LF>的位置)或紧随任何“非单词”字符的位置。下一个字符不必是“单词”字符。

\>必须是正则表达式中的最后一个术语。如果有其他字符,则该正则表达式将不匹配任何内容。\>对应于输入的结尾,<CR>之前的位置或任何“非单词”字符之前的位置。前面的字符不必是“单词”字符。

这是“非单词”字符的完整列表,表示为十进制字节码。注意-此列表是在美国计算机上编译的。我不知道其他语言可能对该列表产生什么影响。

001   028   063   179   204   230
002   029   064   180   205   231
003   030   091   181   206   232
004   031   092   182   207   233
005   032   093   183   208   234
006   033   094   184   209   235
007   034   096   185   210   236
008   035   123   186   211   237
009   036   124   187   212   238
011   037   125   188   213   239
012   038   126   189   214   240
014   039   127   190   215   241
015   040   155   191   216   242
016   041   156   192   217   243
017   042   157   193   218   244
018   043   158   194   219   245
019   044   168   195   220   246
020   045   169   196   221   247
021   046   170   197   222   248
022   047   173   198   223   249
023   058   174   199   224   250
024   059   175   200   226   251
025   060   176   201   227   254
026   061   177   202   228   255
027   062   178   203   229

正则表达式字符类范围[xy]
字符类范围无法正常工作。看到以下问题:为什么findstr无法正确处理大小写(在某些情况下)?,以及以下答案:https : //stackoverflow.com/a/8767815/1012053

问题是FINDSTR不会按字节码值整理字符(通常认为是ASCII码,但ASCII仅从0x00-0x7F定义)。大多数正则表达式实现会将[AZ]视为所有大写英文大写字母。但是FINDSTR使用的排序顺序大致与SORT的工作方式相对应。因此,[AZ]包括完整的英文字母,大写和小写(“ a”除外)以及带有变音符号的非英文字母字符。

以下是FINDSTR支持的所有字符的完整列表,按FINDSTR用于建立正则表达式字符类范围的排序顺序进行排序。字符表示为其十进制字节代码值。我相信如果使用代码页437查看字符,则整理顺序最有意义。注意-此列表是在美国计算机上编译的。我不知道其他语言可能对该列表产生什么影响。

001
002
003
004
005
006
007
008
014
015
016
017
018           
019
020
021
022
023
024
025
026
027
028
029
030
031
127
039
045
032
255
009
010
011
012
013
033
034
035
036
037
038
040
041
042
044
046
047
058
059
063
064
091
092
093
094
095
096
123
124
125
126
173
168
155
156
157
158
043
249
060
061
062
241
174
175
246
251
239
247
240
243
242
169
244
245
254
196
205
179
186
218
213
214
201
191
184
183
187
192
212
211
200
217
190
189
188
195
198
199
204
180
181
182
185
194
209
210
203
193
207
208
202
197
216
215
206
223
220
221
222
219
176
177
178
170
248
230
250
048
172
171
049
050
253
051
052
053
054
055
056
057
236
097
065
166
160
133
131
132
142
134
143
145
146
098
066
099
067
135
128
100
068
101
069
130
144
138
136
137
102
070
159
103
071
104
072
105
073
161
141
140
139
106
074
107
075
108
076
109
077
110
252
078
164
165
111
079
167
162
149
147
148
153
112
080
113
081
114
082
115
083
225
116
084
117
085
163
151
150
129
154
118
086
119
087
120
088
121
089
152
122
090
224
226
235
238
233
227
229
228
231
237
232
234

正则表达式字符类术语限制和BUG
FINDSTR不仅在正则表达式中最多限制15个字符类术语,而且它无法正确处理超过限制的尝试。使用16个或更多字符类术语会导致出现一个交互式Windows弹出窗口,提示“查找字符串(QGREP)实用程序遇到问题,需要关闭。对此给您带来的不便,我们深表歉意。” 消息文本根据Windows版本的不同而略有不同。这是一个失败的FINDSTR示例:

echo 01234567890123456|findstr [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]

此错误由DosTips用户Judago 在此处报告。已在XP,Vista和Windows 7上得到确认。

如果
正则表达式搜索包含字节码0xFF(十进制255),则失败(并可能无限期挂起)。任何包含字节代码0xFF(十进制255)的正则表达式搜索都将失败。如果直接包含字节码0xFF或隐式包含在字符类范围内,则失败。请记住,FINDSTR字符类范围不会根据字节码值整理字符。字符<0xFF>出现在<space><tab>字符之间的排序顺序中相对较早。因此,同时包含<space>和的任何字符类范围都<tab>将失败。

确切的行为会略有变化,具体取决于Windows版本。如果包含0xFF,Windows 7将无限期挂起。XP不会挂起,但始终找不到匹配项,并且偶尔会显示以下错误消息- “该进程试图写入不存在的管道。”

我无法再使用Vista机器,因此无法在Vista上进行测试。

正则表达式错误:.并且[^anySet]可以匹配文件结尾
正则表达式.元字符只能匹配<CR>或以外的任何字符<LF>。如果文件中的最后一行未以<CR>或终止,则存在一个错误使它可以匹配文件结尾<LF>。但是,.将不匹配空文件。

例如,一个名为“ test.txt”的文件包含一行x,而没有终止<CR><LF>,则将与以下内容匹配:

findstr /r x......... test.txt

此错误已在XP和Win7上得到确认。

否定字符集似乎也是如此。类似的东西[^abc]将匹配文件结束。正面的字符集[abc]似乎可以正常工作。我只在Win7上测试过。


1
findstr在处理大型文件时也很麻烦。文件> 2GB可能导致findstr挂起。它并不总是会发生。为了确认错误,我搜索了一个2.3GB的文件,该文件没有挂起。即使仅搜索单个文件,它也会挂起。解决方法是将的输出通过管道传递typefindstr
幻灭了

值得一提的是,它还findstr支持多个/c:搜索字符串。我知道您的回答确实证明了这一点。但这是没有记录的东西。在没有使用findstr它几年之后,我对它的功能感到非常惊讶。
幻灭了

@CraigYoung-您对搜索字符串源是正确的。我修改了答案,谢谢。
dbenham 2014年

1
经过进一步调查,它看起来像是LF您记录的问题的变体。我意识到我的测试文件并没有以结尾结尾,LF因为我使用copy了追加模式来创建它。我放置了一个命令行会话来将问题演示给答案(stackoverflow.com/a/22943056/224704)。请注意,输入重定向,但是搜索挂起。完全相同的搜索命令不会与较小的文件(不会以)结尾挂起LF
幻灭了

1
新发现(Win7的):findstr /R /C:"^[0-9][0-9]* [0-3][0-9][0-9]-[0-9][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9]* [0-9]*\.[0-9]*"(15字符类) - ErrorLevel = -1073740791 (0xC0000409)错误对话框窗口Find String (QGREP) Utility has stopped working; 删除一类或两个元字符(*\.)后,它可以工作...
aschipfl

7

findstr 搜索大文件时,有时会意外挂起。

我尚未确认确切条件或边界大小。我怀疑任何大于2GB的文件都可能有危险。

我对此有不同的经验,所以它不仅仅是文件大小。如果重定向的输入不以LF结尾,这看起来可能是XP和Windows 7FINDSTR挂起的一种变体,但是正如所演示的,当输入未被重定向时,这个特殊的问题就显现出来了。

以下命令行会话(Windows 7)演示了如何findstr搜索3GB文件时挂起。

C:\Data\Temp\2014-04>echo 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890> T100B.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,10) do @type T100B.txt >> T1KB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1KB.txt >> T1MB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1MB.txt >> T1GB.txt

C:\Data\Temp\2014-04>echo find this line>> T1GB.txt

C:\Data\Temp\2014-04>copy T1GB.txt + T1GB.txt + T1GB.txt T3GB.txt
T1GB.txt
T1GB.txt
T1GB.txt
        1 file(s) copied.

C:\Data\Temp\2014-04>dir
 Volume in drive C has no label.
 Volume Serial Number is D2B2-FFDF

 Directory of C:\Data\Temp\2014-04

2014/04/08  04:28 PM    <DIR>          .
2014/04/08  04:28 PM    <DIR>          ..
2014/04/08  04:22 PM               102 T100B.txt
2014/04/08  04:28 PM     1 020 000 016 T1GB.txt
2014/04/08  04:23 PM             1 020 T1KB.txt
2014/04/08  04:23 PM         1 020 000 T1MB.txt
2014/04/08  04:29 PM     3 060 000 049 T3GB.txt
               5 File(s)  4 081 021 187 bytes
               2 Dir(s)  51 881 050 112 bytes free
C:\Data\Temp\2014-04>rem Findstr on the 1GB file does not hang

C:\Data\Temp\2014-04>findstr "this" T1GB.txt
find this line

C:\Data\Temp\2014-04>rem On the 3GB file, findstr hangs and must be aborted... even though it clearly reaches end of file

C:\Data\Temp\2014-04>findstr "this" T3GB.txt
find this line
find this line
find this line
^C
C:\Data\Temp\2014-04>

请注意,我已经在十六进制编辑器中验证了所有行都以终止CRLF。唯一的异常是文件0x1A工作方式copy而终止。但是请注意,此异常不会对“小”文件造成问题

通过其他测试,我确认了以下几点:

  • copy/b二进制文件选项一起使用可防止添加0x1A字符,并且findstr不会挂在3GB文件上。
  • 以不同的字符终止3GB文件也会导致findstr挂起。
  • 0x1A字符不会对“小”文件造成任何问题。(与其他终止字符类似。)
  • CRLF之后添加即可0x1A解决问题。(LF就其本身而言可能就足够了。)
  • type用于将文件通过管道传输到findstr工程中而无需挂起。(这可能是由于其中之一的副作用,type或者|是插入了额外的行尾)。
  • 使用重定向的输入<也会导致findstr挂起。但这是预料之中的。正如dbenham的帖子中所述:“重定向的输入必须以LF” 结尾

1
+1,我可以在Win7机器上确认问题。当最后一个字符不存在时,将挂起一个大小为2GiB的文件<LF>。一个小两个字节的文件没有挂起。很讨厌!
dbenham

6

当括号中包含多个命令并且将文件重定向到整个块时:

< input.txt (
   command1
   command2
   . . .
) > output.txt

...然后,只要块中的命令处于活动状态,文件就保持打开状态,因此命令可以移动重定向文件的文件指针。MORE和FIND命令都将Stdin文件指针移至文件的开头,然后再对其进行处理,因此同一文件可能在块中被处理了几次。例如,此代码:

more < input.txt >  output.txt
more < input.txt >> output.txt

...产生的结果与此相同:

< input.txt (
   more
   more
) > output.txt

这段代码:

find    "search string" < input.txt > matchedLines.txt
find /V "search string" < input.txt > unmatchedLines.txt

...产生的结果与此相同:

< input.txt (
   find    "search string" > matchedLines.txt
   find /V "search string" > unmatchedLines.txt
)

FINDSTR是不同的;它不是标准输入文件指针从当前位置移动。例如,此代码在搜索行之后插入新行:

call :ProcessFile < input.txt
goto :EOF

:ProcessFile
   rem Read the next line from Stdin and copy it
   set /P line=
   echo %line%
   rem Test if it is the search line
   if "%line%" neq "search line" goto ProcessFile
rem Insert the new line at this point
echo New line
rem And copy the rest of lines
findstr "^"
exit /B

我们可以在辅助程序的帮助下充分利用此功能,该辅助程序允许我们移动重定向文件的文件指针,如本示例所示。

这种行为是jeb此岗位上首次报道的。


编辑2018-08-18报告了新的FINDSTR错误

FINDSTR命令有一个奇怪的错误,当此命令用于以彩色显示字符并且此命令的输出重定向到CON设备时,会发生此错误。有关如何使用FINDSTR命令以彩色显示文本的详细信息,请参见本主题

当这种形式的FINDSTR命令的输出重定向到CON时,以期望的颜色输出文本后会发生一些奇怪的事情:将所有文本输出为“不可见”字符,尽管更精确的描述是该文本是输出为黑色背景上的黑色文本。如果您使用COLOR命令重置整个屏幕的前景色和背景色,则将显示原始文本。但是,当文本为“不可见”时,我们可以执行SET / P命令,因此输入的所有字符都不会出现在屏幕上。此行为可能用于输入密码。

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"

2

我想报告一个错误,该错误涉及在文件名中使用破折号(-)或破折号(-)时在第一个答案中搜索的数据源部分。

更具体地说,如果您要使用第一个选项-将文件名指定为arguments,将找不到该文件。一旦使用选项2- 通过重定向的stdin或选项3- 来自管道的数据流,findstr就会找到该文件。

例如,以下简单的批处理脚本:

echo off
chcp 1250 > nul
set INTEXTFILE1=filename with – dash.txt
set INTEXTFILE2=filename with — dash.txt

rem 3 way of findstr use with en dashed filename
echo.
echo Filename with en dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE1%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE1%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE1%" | findstr .
echo.
echo.
rem The same set of operations with em dashed filename
echo Filename with em dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE2%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE2%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE2%" | findstr .
echo.

pause

将打印:

带破折号的文件名:

  1. 作为参数
    FINDSTR:无法使用-dash.txt打开文件名

  2. 作为通过重定向的标准输入,
    我是带破折号的文件。

  3. 作为来自管道的数据流,
    我是带破折号的文件。

带破折号的文件名:

  1. 作为参数
    FINDSTR:无法使用-dash.txt打开文件名

  2. 作为通过重定向的标准输入,
    我是带破折号的文件。

  3. 作为来自管道的数据流,
    我是带有破折号的文件。

希望能帮助到你。

M.


1
嗨,马特罗,虽然您的评论可能是正确的,但我不确定他们是否未解决实际问题。
Wai Ha Lee

我相信这是Unicode问题,FINDSTR不支持。CMD.EXE重定向可以正确地使用Unicode打开文件名,就像TYPE命令一样。但是在这条线上的某个地方,FINDSTR会将破折号和全破折号都转换为普通破折号,并且操作系统当然找不到该名称。如果您创建另一个文件,用破折号代替破折号和/或破折号,则FINDSTR将搜索破折号文件(如果提供的名称中包含破折号或破折号)。
dbenham 2015年

我将此问题归类为限制而非错误。
dbenham

实际上,这不是扩展Unicode的Unicode问题。我已经在原始答案的命令行参数字符限制-扩展ASCII转换标题下记录了此问题。FINDSTR将许多扩展的ASCII代码转换为“相关的”真实ASCII,包括破折号和破折号。
dbenham '16

1

假定没有无效或不兼容的开关,并且没有搜索字符串超过适用的长度限制,该findstr命令ErrorLevel(或退出代码)设置为以下值之一:

  • 0 在所有指定文件的一行中至少遇到一个匹配项时;
  • 1 除此以外;

在以下情况下,一行被认为包含匹配项:

  • 没有/V给出选项,并且搜索表达式至少出现一次;
  • /V选项已给出,搜索表达式不会出现;

这意味着,/V选项也改变了回来ErrorLevel,但它并不会只是恢复它!

例如,当你有一个文件test.txt有两行,其中一个包含字符串text,但另一个没有,这两个findstr "text" "test.txt"findstr /V "text" "test.txt"返回ErrorLevel0

基本上可以说:如果findstr至少返回一行,ErrorLevel则设置为0,否则返回1

请注意,该/M选项不会影响该ErrorLevel值,它只会更改输出。

(仅出于完整性考虑:该find命令/V选项和选项上的行为完全相同ErrorLevel/C选项不影响ErrorLevel。)


1

FINDSTR有一个颜色错误,我在/superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to中描述并解决了-findstr / 1538802?noredirect = 1#comment2339443_1538802

概括地说,该线程的错误是,如果将输入通过管道传递给带括号的代码块中的FINDSTR,则内联ANSI转义颜色代码将在以后执行的命令中停止工作。内联颜色代码的示例是:(echo %magenta%Alert: Something bad happened%yellow%其中洋红色和黄色是.bat文件中先前定义为相应的ANSI转义颜色代码的var)。

我最初的解决方案是在FINDSTR之后调用不执行子程序。无论如何,呼叫或返回“重置”都需要重置。

后来,我发现了另一个可能更有效的解决方案:将FINDSTR短语放在括号中,如以下示例所示: echo success | ( FINDSTR /R success ) 将FINDSTR短语放在嵌套的代码块中似乎可以隔离FINDSTR的colorcode错误,因此不会影响嵌套外部的内容。块。也许这项技术还将解决其他一些不希望的FINDSTR副作用


很棒的发现。但是您的规则可以简化(至少在我的企业Windows 10计算机上)。FINDSTR阻止所有控制台转义序列对同一命令块中的后续命令起作用。FINDSTR是读取管道,重定向输入还是文件都没有关系。转义序列故障不仅限于颜色代码。命令块是括号内的任何命令集,和/或通过&,&&,或||连接的命令。
dbenham

@dbenham:这个问题很好的概括。您是否知道我的解决方案(将FINDSTR短语嵌套在括号内)在一般情况下是否也有效?而且您知道我的解决方案是否有不良副作用吗?
Dolores Stevens

我没有做任何详尽的测试,但是是的,嵌套括号似乎是一个通用的解决方案,而且我想不出任何可能的不良副作用。
dbenham

-1

/ D提示多个目录:将目录列表放在搜索字符串之前。所有这些工作:

findstr /D:dir1;dir2 "searchString" *.*
findstr /D:"dir1;dir2" "searchString" *.*
findstr /D:"\path\dir1\;\path\dir2\" "searchString" *.*

不出所料,如果您不使用开头目录,则该路径是相对于位置的\"如果目录名称中没有空格,则在路径周围使用可选。结尾\是可选的。location的输出将包括您提供的任何路径。无论是否在目录列表中加,它都可以使用"


我在这里看不到任何未记录的内容。/ D选项在内置帮助中进行了描述。这不是有关如何使用FINDSTR的一般提示的问题。严格旨在列出未记录的功能,限制和/或错误。
dbenham 2015年

1
@dbenham是的,它并不是真正没有记载的东西,但是我发现我不得不与findstr讨好,以获得想要的结果,并分享我发现DID可以正常工作的东西,这样人们就不会浪费时间去尝试不起作用的命令。hth(很遗憾,您不喜欢我的输入-只是为了具有建设性)
gordon 2015年

恕我直言,/ D开关在内置帮助中有明确说明:/D:dirlist Search a semicolon-delimited list of directories它位于搜索字符串之前,因此我不明白“ / D”开关在“您找到的内容”中到底是什么(以及“不能正常工作”)...
Aacini 2015年

@Aacini在许多语言中,属性的顺序无关紧要。我首先了解findstr列表/ D 的文档。是的,我对此功能没有论据,只是关于属性顺序很重要的陷阱没有记载。我很少做命令行工作,所以当我在整理一条命令时,不知道顺序有所不同,我只是在添加属性时添加它们(按字母顺序,C在D之前)。我感到非常沮丧,并与其他在命令行中工作不多的人分享了我的“发现”经验。
戈登

1
可选属性的顺序通常无关紧要。该findstr文件规定,strings部分是可选的,则必须在以后把它可选属性和之前可选的文件名列表。如果“您的发现”是使用不遵循其用法格式的命令会导致错误,则说明了这一点。请参阅命令语法“语法以必须键入命令的顺序显示及其后的任何参数”
Aacini
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.