什么是Windows FINDSTR命令的未公开的function和限制?

Windows FINDSTR命令是可怕的logging。 有非常基本的命令行帮助可以通过FINDSTR /? ,或HELP FINDSTR ,但它是可悲的不足。 在http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/findstr.mspx?mfr=true上可以find更多的文档。

有很多FINDSTR的function和限制,甚至没有暗示在文档中。 如果没有事先的知识和/或小心的试验,也不能预料到它们。

所以问题是 – 什么是无证FINDSTR的function和限制?

这个问题的目的是提供许多未logging的function的一站式存储库,以便:

A)开发人员可以充分利用那里的function。

B)开发人员不要浪费时间想知道为什么某些东西不应该工作。

请确保您在回复之前知道现有的文档。 如果信息被HELP覆盖,那么它不属于这里。

这也不是一个显示FINDSTR的有趣用途的地方。 如果一个逻辑人可以基于文档预测FINDSTR的特定用法的行为,那么它就不属于这里。

同样的道理,如果一个逻辑人可以基于任何现有答案中包含的信息来预测特定用法的行为,那么它又不属于这里。

前言
这个答案中的大部分信息都是基于在Vista机器上运行的实验收集的。 除非另有明确规定,否则我还没有确认这些信息是否适用于其他Windows版本。

FINDSTR输出
文档从来不会解释FINDSTR的输出。 这暗示了匹配行被打印的事实,但仅此而已。

匹配行输出格式如下:

文件名:行号:lineOffset:文本

哪里

fileName: =包含匹配行的文件的名称。 如果请求显式为单个文件,或者searchpipe道input或redirectinput,则不会打印文件名。 打印时,fileName将始终包含提供的所有path信息。 如果使用/S选项,将会添加其他path信息。 打印path总是相对于提供的path,或相对于当前目录(如果没有提供)。

注 – 通过使用非标准(且logging不当)通配符 <>来search多个文件时,可以避免使用文件名前缀。 这些通配符如何工作的确切规则可以在这里find。 最后,你可以看看这个非标准通配符如何与FINDSTR一起工作的例子 。

lineNumber: =表示为十进制值的匹配行的行号,其中1表示input的第一行。 只有在指定/N选项时才会打印。

lineOffset: =匹配行开头的十进制字节偏移量,0表示第一行的第一个字符。 只有在指定/O选项时才会打印。 这不是线内匹配的偏移。 它是从文件开头到行首的字节数。

text =匹配行的二进制表示,包括任何<CR>和/或<LF>。 二进制输出中没有任何内容,这样匹配所有行的这个例子将产生原始文件的确切的二进制拷贝。

 FINDSTR "^" FILE >FILE_COPY 

大多数控制字符和许多扩展的ASCII字符在XP上显示为点
在XP上的FINDSTR在屏幕上显示来自匹配线的大多数不可打印的控制字符作为点(周期)。 以下控制字符是例外; 它们显示为:0x09制表符,0x0A LineFeed,0x0B垂直制表符,0x0C换页符,0x0D回车符。

XP FINDSTR也将一些扩展的ASCII字符转换为点。 在XP上显示为点的扩展ASCII字符与在命令行上提供的字符相同。 请参阅本文后面的“命令行参数的字符限制 – 扩展ASCII转换”部分

如果输出是pipe道,redirect到文件或在FOR IN()子句中,则控制字符和扩展ASCII不会在XP上转换为点。

Vista和Windows 7总是显示所有的字符,而不是点。

返回码(ERRORLEVEL)

  • 0(成功)
    • 匹配在至less一个文件的至less一行中find。
  • 1(失败)
    • 在任何文件的任何一行中都找不到匹配项。
    • /A:xx选项指定的颜色无效
  • 2(错误)
    • 指定了不兼容的选项/L/R
    • /A:/F:/C:/D:/G:
    • /F:file/G:file找不到的/G:file
  • 255(错误)
    • 太多的正则expression式字符类术语
      请参阅答案的第2部分中的正则expression式字符类限制和BUG

要search的数据源 (根据Windows 7的testing更新)
Findstr只能从以下来源之一search数据:

  • 指定为参数的文件名和/或使用/F:file选项。

  • stdin通过redirectfindstr "searchString" <file

  • 来自pipe道type file | findstr "searchString"数据streamtype file | findstr "searchString" type file | findstr "searchString"

参数/选项优先于redirect,优先于pipe道数据。

文件名参数和/F:file可以合并。 可以使用多个文件名参数。 如果指定了多个/F:file选项,则只使用最后一个。 通配符在文件名参数中是允许的,但不在/F:file指向的/F:file

searchstring的来源 (基于Windows 7的testing更新)
/G:file/C:string选项可以组合。 可以指定多个/C:string选项。 如果指定了多个/G:file选项,则只使用最后一个。 如果使用/G:file/C:string ,则所有非选项参数都假定为要search的文件。 如果既不使用/G:file也不使用/C:string ,则第一个非选项参数将被视为空格分隔的search项列表。

使用/F:FILE选项时,不得在文件中引用文件名。
文件名可能包含空格和其他特殊字符。 大多数命令都要求引用这样的文件名。 但是FINDSTR /F:files.txt选项要求files.txt中的文件名不能被引用。 如果名称被引用,文件将不会被find。

BUG – 短8.3文件名可以打破/D/S选项
和所有Windows命令一样,FINDSTR在查找要search的文件时将尝试匹配长名称和短名称。 假设当前文件夹包含以下非空文件:

 b1.txt b.txt2 c.txt 

以下命令将成功查找所有3个文件:

 findstr /m "^" *.txt 

b.txt2匹配,因为相应的短名称B9F64~1.TXT匹配。 这与所有其他Windows命令的行为一致。

但是使用/D/S选项的错误会导致以下命令只能findb1.txt

 findstr /m /d:. "^" *.txt findstr /m /s "^" *.txt 

该错误可防止findb.txt2 ,以及在同一目录下的b.txt2之后sorting的所有文件名。 find之前sorting的其他文件,如a.txt 。 稍后sorting的其他文件(如d.txt )会在错误触发后错过。

search的每个目录都被独立处理。 例如, /S选项将无法在父文件中find文件后成功地开始在子文件夹中search,但是一旦该错误导致子文件中缺less短文件名,则该子文件夹中的所有后续文件也会错过了。

如果在禁用了NTFS 8.3名称生成的计算机上创build了相同的文件名,则这些命令将无错误。 当然b.txt2不会被发现,但c.txt会被正确地find。

不是所有的短名称都会触发错误。 我所看到的所有bug行为的实例都包含一个长度超过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选项跳过该文件。

pipe道和redirectinput可能会附加<CR><LF>
如果inputinput并且stream的最后一个字符不是<LF> ,那么FINDSTR将自动将<CR><LF>附加到input。 这已经在XP,Vista和Windows 7上得到了证实。 (我以前认为Windowspipe道负责修改input,但是我发现FINDSTR实际上正在进行修改。)

Vista上的redirectinput也是如此。 如果用作redirectinput的文件的最后一个字符不是<LF> ,那么FINDSTR将自动将<CR><LF>附加到input。 但是,XP和Windows 7不会改变redirectinput。

如果redirectinput不以<LF>结尾,则FINDSTR挂在XP和Windows 7上
这是XP和Windows 7上一个令人讨厌的“特性”。如果用作redirectinput的文件的最后一个字符不是以<LF>结尾,那么FINDSTR一旦到达redirect文件的末尾就会无限期地挂起。

如果pipe状数据由单个字符组成,则最后一行数据可能会被忽略
如果input是input的,而最后一行由一个没有跟在<LF>后面的单个字符组成,那么FINDSTR将完全忽略最后一行。

示例 – 单个字符且没有<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来testing)。

选项语法
选项可以用/-作为前缀-选项可以连在一个/- 。 但是,连接选项列表最多可以包含一个多字符选项,如OFF或F :,多字符选项必须是列表中的最后一个选项。

以下所有对任何包含“hello”和“goodbye”行的expression式不区分大小写的正则expression式search都是等价的方法

  • /i /r /c:"hello.*goodbye" /c:"goodbye.*hello"

  • -i -r -c:"hello.*goodbye" /c:"goodbye.*hello"

  • /irc:"hello.*goodbye" /c:"goodbye.*hello"

searchstring长度限制
在Vista上,单个searchstring的最大允许长度是511字节。 如果任何searchstring超过511则结果是一个FINDSTR: Search string too long. ERRORLEVEL 2错误。

进行正则expression式search时,最大searchstring长度为254.长度为255到511的正则expression式将导致FINDSTR: Out of memory与ERRORLEVEL 2 FINDSTR: Out of memory不足错误。正则expression式长度> 511会导致FINDSTR: Search string too long. 错误。

在Windows XP上,searchstring的长度显然更短。 Findstr错误:“searchstring太长”:如何提取和匹配“for”循环中的子string? 对于文字和正则expression式search,XP的限制是127个字节。

行长度限制
指定为命令行参数或通过/ F:FILE选项的文件没有已知的行长度限制。 search已成功运行,不包含单个<LF>的128MB文件。

pipe道数据和redirectinput限制为每行8191字节。 这个限制是FINDSTR的一个“特征”。 这不是固有的pipe道或redirect。 使用redirect的标准input或pipe道input的FINDSTR将永远不匹配任何> = 8k字节的行。 Lines> = 8k会向stderr生成错误消息,但是如果在至less一个文件的至less一行中findsearchstring,则ERRORLEVEL仍然为0。

默认searchtypes:文字与正则expression式
/C:"string" – 默认是/ L文字。 显式地将/ L选项与/ C:“string”组合起来肯定是有效的,但却是多余的。

"string argument" – 默认取决于第一个searchstring的内容。 (请记住<space>用于分隔searchstring。)如果第一个searchstring是包含至less一个未转义的元字符的有效正则expression式,则所有searchstring将被视为正则expression式。 否则,所有searchstring将被视为文字。 例如, "51.4 200"将被视为两个正则expression式,因为第一个string包含一个未转义的点,而"200 51.4"将被视为两个文字,因为第一个string不包含任何元字符。

/G:file – 默认取决于/G:file中第一个非空行的内容。 如果第一个searchstring是一个包含至less一个未转义元字符的有效正则expression式,则所有searchstring将被视为正则expression式。 否则,所有searchstring将被视为文字。

build议 – 使用"string argument"/G:file时,请始终明确指定/L文字选项或/R正则expression式选项。

错误 – 指定多个文字searchstring可能会导致不可靠的结果

以下简单的FINDSTR示例即使应该也找不到匹配项。

 echo ffffaaa|findstr /l "ffffaaa faffaffddd" 

这个错误已经在Windows Server 2003,Windows XP,Vista和Windows 7上得到确认。

根据实验,如果满足以下所有条件,FINDSTR可能会失败:

  • search使用多个文字searchstring
  • searchstring具有不同的长度
  • 短searchstring与较长的searchstring有一些重叠
  • search区分大小写(无/I选项)

在我看到的每一次失败中,它总是失败的较短searchstring之一。

有关更多信息,请参阅为什么不带有多个文字searchstring的FINDSTR示例find匹配项?

命令行参数中的引号和后缀 – 注意:
这个突出部分中的信息不是100%准确的。 在我写这部分之后,用户MC ND指出了一个引用,它logging了Microsoft C / C ++库如何parsing参数 。 这是非常复杂的,但它似乎准确地预测了FINDSTR命令行参数的反斜杠和引用规则。 我build议您使用下面突出显示的信息作为指导,但是如果您想要更准确的信息,请参阅链接。

在命令行searchstring中转义引号
命令行searchstring中的引号必须使用\"这样的反斜线进行转义。对于文本string和正则expression式searchstring都是如此。这些信息已在XP,Vista和Windows 7上得到确认。

注意:对于CMD.EXEparsing器,引号可能也需要被转义,但这与FINDSTR无关。 例如,要search可以使用的单引号:

FINDSTR \^" file && echo found || echo not found

在命令行文字searchstring中转义反斜杠
字面searchstring中的反斜杠通常可以表示为\\\ 。 它们通常是等价的。 (在Vista中可能会出现一些不寻常的情况,在这种情况下,反斜杠必须总是被转义出来,但是我不再需要一台Vista机器来testing)

但有一些特殊情况:

当search连续的反斜杠时,除了最后一个以外,都必须转义。 最后的反斜杠可以select性地转义。

  • \\可以编码为\\\\\\\
  • \\\可以编码为\\\\\\\\\\\\

在报价之前search一个或多个反斜杠是奇怪的。 逻辑会build议报价必须逃脱,每个主要的反斜杠将需要逃脱,但这是行不通的! 相反,每个主要的反斜杠都必须被双重转义,并且引号通常被转义:

  • \"必须编码为\\\\\"
  • \\"必须编码为\\\\\\\\\"

如前所述,对于CMDparsing器,一个或多个转义引号也可能需要用^转义

本节中的信息已在XP和Windows 7上得到确认。

在命令行中使用正则expression式searchstring转义反斜杠

  • 仅适用Vista:正则expression式中的反斜杠必须或者像\\\\一样被双重转义,否则单个像字符类一样在[\\]

  • XP和Windows 7:正则expression式中的反斜杠总是可以表示为[\\] 。 它通常可以表示为\\ 。 但是,如果反斜杠在转义引用之前,这将不起作用。

    在转义引号之前的一个或多个反斜杠必须被双重转义,否则编码为[\\]

    • \"可能被编码为\\\\\"[\\]\"
    • \\"可能会被编码为\\\\\\\\\"

在/ G:FILE文字searchstring中转义引号和反斜线
由/ G:文件指定的文字searchstring文件中的独立引号和反斜杠不需要转义,但它们可以是。

"\"是等同的。

\\\是等同的。

如果意图是要find\\,那么至less必须避开前面的反斜杠。 \\\\\\\工作。

如果意图find\“,那么至less必须避免引导反斜杠。 \\"\\\"工作。

在/ G:FILE正则expression式searchstring中转义引号和反斜线
这是转义序列根据文档按预期工作的一种情况。 Quote不是正则expression式元字符,所以它不需要转义(但可以)。 反斜杠是一个正则expression式元字符,所以它必须被转义。

命令行参数的字符限制 – 扩展的ASCII转换
空字符(0x00)不能出现在命令行上的任何string中。 任何其他单字节字符都可以出现在string(0x01 – 0xFF)中。 但是,FINDSTR将在命令行参数中find的许多扩展ASCII字符转换为其他字符。 这在两方面产生重大影响:

1)如果用作命令行中的searchstring,许多扩展的ASCII字符将不匹配。 这个限制对于文字和正则expression式的search是一样的。 如果searchstring必须包含扩展的ASCII,则应该使用/G:FILE选项。

2)如果名称包含扩展的ASCII字符,并且在命令行中指定了文件名,则FINDSTR可能无法find文件。 如果要search的文件在名称中包含扩展的ASCII,则应该使用/F:FILE选项。

这是FINDSTR在命令行string上执行的扩展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> )的最简单方法是将它们放入环境variables中,并在命令行参数中使用延迟扩展。

在/ G:FILE和/ F:FILE选项指定的文件中find的string的字符限制
nul(0x00)字符可以出现在文件中,但它的function类似于Cstring终结符。 nul字符之后的任何字符都被视为不同的string,就像它们在另一行上一样。

<CR><LF>字符被视为终止string的行终止符,并不包含在string中。

所有其他单字节字符完全包含在一个string中。

searchUnicode文件
FINDSTR无法正确search大多数Unicode(UTF-16,UTF-16LE,UTF-16BE,UTF-32),因为它无法searchnul字节,Unicode通常包含许多nul字节。

但是,TYPE命令将带有BOM的UTF-16LE转换为单字节字符集,因此类似下面的命令可以使用带有BOM的UTF-16LE。

 type unicode.txt|findstr "search" 

请注意,您的活动代码页不支持的Unicode代码点将被转换为? 字符。

只要您的searchstring只包含ASCII,就可以searchUTF-8。 但是,任何多字节UTF-8字符的控制台输出将不正确。 但是,如果将输出redirect到文件,则结果将被正确编码为UTF-8。 请注意,如果UTF-8文件包含物料清单,那么物料清单将被视为第一行的一部分,这可能会导致与行的开头匹配的search。

如果将searchstring放在UTF-8编码的search文件(不含BOM)中,并使用/ G选项,则可以search多字节UTF-8字符。

行结束
FINDSTR在每个<LF>之后立即断行。 <CR>的存在或不存在对换行没有影响。

通过换行符search
正如预期的那样. 正则expression式元字符不会匹配<CR>或<LF>。 但是可以使用命令行searchstringsearch整个换行符。 <CR>和<LF>字符都必须显式匹配。 如果find多行匹配,则仅打印匹配的第一行。 然后FINDSTR再次回到源代码中的第二行,并重新开始search – 类似于“向前看”types的function。

假设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选项跨越换行符search是不准确的,因为匹配<CR>或<LF>的唯一方法是通过三明治EOL字符的正则expression式字符类范围expression式。

  • [<TAB>-<0x0B>]匹配<LF>,但也匹配<TAB>和<0x0B>

  • [<0x0C>-!]匹配<CR>,但也匹配<0x0C>和!

    注意 – 以上是正则expression式字节stream的符号表示,因为我不能以graphics方式表示字符。

下面第二部分继续回答…

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

有限的正则expression式(正则expression式)支持
FINDSTR对正则expression式的支持是非常有限的。 如果它不在帮助文档中,则不支持。

除此之外,所支持的正则expression式是以完全非标准的方式实现的,因此结果可能会不同于预期来自grep或perl之类的结果。

正则expression式位置锚点^和$
^匹配inputstream的开头以及紧跟在<LF>之后的任何位置。 由于FINDSTR也在<LF>之后断行,因此一个简单的“^”正则expression式将始终匹配文件中的所有行,即使是二进制文件。

$匹配紧接在<CR>之前的任何位置。 这意味着包含$的正则expression式searchstring将永远不会匹配Unix样式文本文件中的任何行,也不会匹配Windows文本文件的最后一行,如果它缺less<CR> <LF>的EOL标记。

注意:如前所述,input到FINDSTR的input和redirectinput可能附有<CR><LF> ,但不在源代码中。 显然这可能会影响使用$的正则expression式search。

任何含有^之前或之后的字符的searchstring将始终无法find匹配项。

位置选项/ B / E / X
位置选项的作用与^$相同,除了它们也适用于文字searchstring。

/ B的function与正则expression式searchstring开头的^相同。

/ E的作用与正则expression式searchstring结尾处的$相同。

/ X的function与在正则expression式searchstring的开头和$都有相同的function。

正则expression式边界
\<必须是正则expression式中的第一个术语。 正则expression式不会匹配任何其他字符在它之前。 \<对应于input的开始,行的开始(紧跟在<LF>之后的位置)或紧跟在任何“非单词”字符之后的位置。 下一个字符不需要是“单词”字符。

\>必须是正则expression式中的最后一项。 正则expression式不会匹配任何其他字符跟随它。 \>对应于input的结尾,紧接在<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 

正则expression式字符类的范围[xy]
字符类范围不能按预期工作。 看到这个问题: 为什么findstr不正确地处理案件(在某些情况下)? ,以及这个答案: https : //stackoverflow.com/a/8767815/1012053 。

问题是FINDSTR不能通过字节代码值(通常认为是ASCII代码,但是ASCII只定义在0x00 – 0x7F)来对字符进行sorting。 大多数正则expression式实现将[AZ]视为所有大写英文大写字母。 但是FINDSTR使用大致对应于SORT如何工作的sorting顺序。 所以[AZ]包括完整的英文字母,包括大写和小写(“a”除外),以及带有变音符的非英文字母字符。

下面是FINDSTR支持的所有字符的完整列表,按FINDSTR使用的sorting顺序sorting,build立正则expression式字符类的范围。 这些字符表示为它们的十进制字节代码值。 如果使用代码页437查看字符,我认为sorting顺序最有意义。 注意 – 此列表是在美国机器上编译的。 我不知道其他语言对这个列表可能有什么影响。

 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 

正则expression式字符类的期限和BUG
在正则expression式中,FINDSTR不仅限于最多15个字符的类别,它不能正确地处理超出限制的尝试。 使用16个或更多的字符类术语导致交互式的Windowspopup窗口显示“查找string(QGREP)实用程序遇到问题,需要closures,我们对此造成的不便深表歉意。 消息文本根据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上得到确认。

Regex searches fail (and may hang indefinitely) if they include byte code 0xFF (decimal 255)
Any regex search that includes byte code 0xFF (decimal 255) will fail. It fails if byte code 0xFF is included directly, or if it is implicitly included within a character class range. Remember that FINDSTR character class ranges do not collate characters based on the byte code value. Character <0xFF> appears relatively early in the collation sequence between the <space> and <tab> characters. So any character class range that includes both <space> and <tab> will fail.

The exact behavior changes slightly depending on the Windows version. Windows 7 hangs indefinitely if 0xFF is included. XP doesn't hang, but it always fails to find a match, and occasionally prints the following error message – "The process tried to write to a nonexistent pipe."

I no longer have access to a Vista machine, so I haven't been able to test on Vista.

Regex bug: . and [^anySet] can match End-Of-File
The regex . meta-character should only match any character other than <CR> or <LF> . There is a bug that allows it to match the End-Of-File if the last line in the file is not terminated by <CR> or <LF> . However, the . will not match an empty file.

For example, a file named "test.txt" containing a single line of x , without terminating <CR> or <LF> , will match the following:

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

This bug has been confirmed on XP and Win7.

The same seems to be true for negative character sets. Something like [^abc] will match End-Of-File. Positive character sets like [abc] seem to work fine. I have only tested this on Win7.

When several commands are enclosed in parentheses and there are redirected files to the whole block:

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

… then the files remains open as long as the commands in the block be active, so the commands may move the file pointer of the redirected files. Both MORE and FIND commands move the Stdin file pointer to the beginning of the file before process it, so the same file may be processed several times inside the block. For example, this code:

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

… produce the same result than this one:

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

此代码:

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

… produce the same result than this one:

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

FINDSTR is different; it does not move the Stdin file pointer from its current position. For example, this code insert a new line after a search line:

 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 

We may make good use of this feature with the aid of an auxiliary program that allow us to move the file pointer of a redirected file, as shown in this example .

This behavior was first reported by jeb at this post .

findstr sometimes hangs unexpectedly when searching large files.

I haven't confirmed the exact conditions or boundary sizes. I suspect any file larger 2GB may be at risk.

I have had mixed experiences with this, so it is more than just file size. This looks like it may be a variation on FINDSTR hangs on XP and Windows 7 if redirected input does not end with LF , but as demonstrated this particular problem manifests when input is not redirected.

The following command line session (Windows 7) demonstrates how findstr can hang when searching a 3GB file.

 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> 

Note, I've verified in a hex editor that all lines are terminated with CRLF . The only anomaly is that the file is terminated with 0x1A due to the way copy works . Note however, that this anomaly doesn't cause a problem on "small" files .

With additional testing I have confirmed the following:

  • Using copy with the /b option for binary files prevents the addition of the 0x1A character, and findstr doesn't hang on the 3GB file.
  • Terminating the 3GB file with a different character also causes a findstr to hang.
  • The 0x1A character doesn't cause any problems on a "small" file. (Similarly for other terminating characters.)
  • Adding CRLF after 0x1A resolves the problem. ( LF by itself would probably suffice.)
  • Using type to pipe the file into findstr works without hanging. (This might be due to a side effect of either type or | that inserts an additional End Of Line.)
  • Use redirected input < also causes findstr to hang. But this is expected; as explained in dbenham's post : "redirected input must end in LF " .

I'd like to report a bug regarding the section Source of data to search in the first answer when using en dash (–) or em dash (—) within the filename.

More specifically, if you are about to use the first option – filenames specified as arguments , the file won't be found. As soon as you use either option 2 – stdin via redirection or 3 – data stream from a pipe , findstr will find the file.

For example, this simple batch script:

 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 

将打印:

Filename with en dash:

  1. As argument
    FINDSTR: Cannot open filename with – dash.txt

  2. As stdin via redirection
    I am the file with an en dash.

  3. As datastream from a pipe
    I am the file with an en dash.

Filename with em dash:

  1. As argument
    FINDSTR: Cannot open filename with – dash.txt

  2. As stdin via redirection
    I am the file with an em dash.

  3. As datastream from a pipe
    I am the file with an em dash.

希望它有帮助。

M.

/D tip for multiple directories: put your directory list before the search string. These all work:

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

As expected, the path is relative to location if you don't start the directories with \ . Surrounding the path with " is optional if there are no spaces in the directory names. The ending \ is optional. The output of location will include whatever path you give it. It will work with or without surrounding the directory list with " .