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

问题描述 投票:178回答:6

Windows FINDSTR命令可怕地记录在案。通过FINDSTR /?HELP FINDSTR可以获得非常基本的命令行帮助,但它非常不合适。在https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr网上有更多的文档。

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

所以问题是 - 未记录的FINDSTR功能和限制是什么?

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

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

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

在回复之前,请确保您知道现有文档。如果HELP涵盖了这些信息,则它不属于此处。

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

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

batch-file cmd findstr
6个回答
270
投票

前言 此答案中的大部分信息都是基于在Vista计算机上运行的实验收集的。除非另有明确说明,否则我尚未确认该信息是否适用于其他Windows版本。

FINDSTR输出 文档从不困扰解释FINDSTR的输出。它暗示了印刷匹配线的事实,但仅此而已。

匹配行输出的格式如下:

文件名:行号:lineOffset:文本

哪里

fileName:=包含匹配行的文件的名称。如果请求明确针对单个文件,或者搜索管道输入或重定向输入,则不会打印文件名。打印时,fileName将始终包含提供的任何路径信息。如果使用/S选项,将添加其他路径信息。打印路径始终相对于提供的路径,或者相对于当前目录(如果未提供)。

注 - 使用non-standard (and poorly documented) wildcards <>搜索多个文件时,可以避免使用文件名前缀。有关这些通配符如何工作的确切规则可以找到here。最后,你可以看看这个example of how the non-standard wildcards work with FINDSTR

lineNumber:=匹配行的行号,表示为十进制值,1表示输入的第一行。仅在指定/N选项时打印。

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

text =匹配行的二进制表示,包括任何&LT; CR>和/或&LT; LF>。二进制输出中没有任何内容,因此匹配所有行的此示例将生成原始文件的精确二进制副本。

FINDSTR "^" FILE >FILE_COPY

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

XP FINDSTR还将许多扩展ASCII字符转换为点。在XP上显示为点的扩展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(错误) 正则表达式字符类术语太多 see Regex character class term limit and BUG in part 2 of answer

要搜索的数据源(基于Windows 7测试更新) Findstr只能搜索以下某个来源的数据:

  • 文件名指定为参数和/或使用/F:file选项。
  • stdin通过重定向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中的文件名。如果引用该名称,则无法找到该文件。

BUG - 短8.3文件名可以打破/D/S选项 与所有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

该bug会阻止找到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不会改变重定向输入。

如果重定向输入不以<LF>结尾,则FINDSTR会在XP和Windows 7上挂起 这是XP和Windows 7上令人讨厌的“功能”。如果用作重定向输入的文件的最后一个字符不以<LF>结尾,那么一旦FINDSTR到达重定向文件的末尾,它将无限期挂起。

如果Piped数据的最后一行由单个字符组成,则可以忽略它 如果输入是管道输入且最后一行由一个未跟随<LF>的单个字符组成,则FINDSTR完全忽略最后一行。

示例 - 具有单个字符但没有<LF>的第一个命令无法匹配,但是具有2个字符的第二个命令工作正常,第三个命令具有一个带有终止换行符的字符。

> set /p "=x" <nul | findstr "^"

> set /p "=xx" <nul | findstr "^"
xx

> echo x| findstr "^"
x

DosTips用户Sponge Belly在new findstr bug报道。在XP,Windows 7和Windows 8上确认。还没有听说过Vista。 (我不再有Vista测试)。

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

以下是对任何包含“hello”和“goodbye”的任何行表达不区分大小写的正则表达式搜索的等效方法

  • /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,那么结果是ERRORLEVEL 2的FINDSTR: Search string too long.错误。

进行正则表达式搜索时,最大搜索字符串长度为254.长度介于255和511之间的正则表达式将导致ERRORLEVEL 2出现FINDSTR: Out of memory错误。正则表达式长度> 511会导致FINDSTR: Search string too long.错误。

在Windows XP上,搜索字符串长度明显更短。 Findstr error: "Search string too long": How to extract and match substring in "for" loop?文字和正则表达式搜索的XP限制为127字节。

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

管道数据和重定向输入限制为每行8191个字节。此限制是FINDSTR的“功能”。它不是管道或重定向所固有的。使用重定向stdin或管道输入的FINDSTR将永远不会匹配> = 8k字节的任何行。 Lines> = 8k会向stderr生成错误消息,但如果在至少一个文件的至少一行中找到搜索字符串,则ERRORLEVEL仍为0。

默认搜索类型:文字与正则表达式 /C:"string" - 默认为/ L literal。将/ L选项与/ C明确组合:“string”当然有效,但是多余。

"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选项)

在我看到的每一次失败中,它总是失败的较短搜索字符串之一。

有关更多信息,请参阅Why doesn't this FINDSTR example with multiple literal search strings find a match?

命令行参数中的引号和后退 注 - 用户MC ND的注释反映了本节的实际可怕的复杂规则。涉及3个不同的解析阶段:

  • 第一个cmd.exe可能需要将某些引号转义为^“(实际上与FINDSTR无关)
  • 接下来FINDSTR使用pre 2008 MS C/C++ argument parser,它有“和\”的特殊规则
  • 在参数解析器完成之后,FINDSTR还将\后跟一个字母数字字符视为文字,但是后跟非字母数字字符作为转义字符

此突出显示部分的其余部分并非100%正确。它可以作为许多情况的指南,但上述规则是完全理解所必需的。

在命令行搜索字符串中转义Quote 必须使用\"等反斜杠转义命令行搜索字符串中的引号。对于文字和正则表达式搜索字符串都是如此。此信息已在XP,Vista和Windows 7上得到确认。

注意:可能还需要为CMD.EXE解析器转义引号,但这与FINDSTR无关。例如,要搜索单个引用,您可以使用:

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

在命令行文字搜索字符串中转义反斜杠 文字搜索字符串中的反斜杠通常可以表示为\\\。它们通常是等价的。 (在Vista中可能会出现异常情况,必须始终反复使用反斜杠,但我不再需要使用Vista计算机进行测试)。

但是有一些特殊情况:

搜索连续反斜杠时,必须转义除最后一个之外的所有反斜杠。最后一个反斜杠可以选择转义。

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

在引用之前搜索一个或多个反斜杠是奇怪的。逻辑会建议必须转义引号,并且每个前导反斜杠都需要转义,但这不起作用!相反,每个前导反斜杠都必须进行双重转义,并且引号会正常转义:

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

如前所述,一个或多个转义引号也可能需要使用^转义为CMD解析器

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

在命令行正则表达式搜索字符串中转义反斜杠

  • 仅限Vista:正则表达式中的反斜杠必须像\\\\一样双重转义,否则单个转义在像[\\]这样的字符类集中
  • XP和Windows 7:正则表达式中的反斜杠始终可以表示为[\\]。它通常可以表示为\\。但是,如果反斜杠在转义引号之前,这就无法工作。 转义引号之前的一个或多个反斜杠必须双重转义,否则编码为[\\] \"可能被编码为\\\\\"[\\]\" \\"可能编码为\\\\\\\\\"[\\][\\]\"\\[\\]\"

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

"\"是等价的。

\\\是等价的。

如果想要找到\\,那么至少必须转义前导反斜杠。 \\\\\\\都工作。

如果意图找到\“,那么至少必须转发前导反斜杠.\\"\\\"都可以工作。

在/ G:FILE正则表达式搜索字符串中转义引号和反斜杠 这是基于文档的转义序列按预期工作的一种情况。引用不是正则表达式元字符,所以它不需要转义(但可以)。反斜杠是一个正则表达式元字符,因此必须进行转义。

命令行参数的字符限制 - 扩展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)中,则可以搜索多字节UTF-8字符,并使用/ G选项。

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

搜索换行符 正如所料,.正则表达式元字符将不匹配 要么 。但是可以使用命令行搜索字符串搜索换行符。这俩 和 必须明确匹配字符。如果找到多行匹配,则仅打印匹配的第一行。 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>]比赛 ,但它也匹配 和<0x0B>
  • [<0x0C>-!]比赛 ,但它也匹配<0x0C>和! 注 - 以上是正则表达式字节流的符号表示,因为我不能以图形方式表示字符。

Answer continued in part 2 below...


62
投票

Answer continued from part 1 above - 我遇到了30,000个字符的答案限制:-(

有限正则表达式(正则表达式)支持 FINDSTR对正则表达式的支持非常有限。如果它不在HELP文档中,则不受支持。

除此之外,支持的正则表达式表达式以完全非标准的方式实现,因此结果可能会有所不同,然后可能会出现类似grep或perl的结果。

正则表达式行位置锚定^和$ ^匹配输入流的开头以及紧随其后的任何位置 。因为FINDSTR之后也会打破线 ,“^”的简单正则表达式将始终匹配文件中的所有行,甚至是二进制文件。

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

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

任何在^之前或$之后带有字符的搜索字符串将始终无法找到匹配项。

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

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

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

/ X的功能与开头的^和正则表达式搜索字符串末尾的$相同。

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

\>必须是正则表达式中的最后一个词。如果任何其他字符跟随它,则正则表达式将不匹配任何内容。 \>对应于输入的结束,即紧接在a之前的位置 ,或紧接任何“非单词”字符之前的位置。前面的字符不必是“单词”字符。

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

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

正则表达式字符类范围[x-y] 字符类范围无法按预期工作。看到这个问题:Why does findstr not handle case properly (in some circumstances)?,以及这个答案:https://stackoverflow.com/a/8767815/1012053

问题是FINDSTR没有按字节代码值整理字符(通常被认为是ASCII代码,但ASCII仅定义为0x00 - 0x7F)。大多数正则表达式实现会将[A-Z]视为所有大写英文大写字母。但FINDSTR使用的排序顺序大致对应于SORT的工作方式。因此[A-Z]包括完整的英文字母,包括大写和小写(“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 here报告了这个错误。它已在XP,Vista和Windows 7上得到确认。

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

确切的行为会根据Windows版本略有变化。如果包含0xFF,Windows 7将无限期挂起。 XP没有挂起,但它始终无法找到匹配项,偶尔会打印以下错误消息 - “进程尝试写入不存在的管道。”

我无法访问Vista机器,所以我无法在Vista上进行测试。

正则表达式错误:.[^anySet]可以匹配End-Of-File 正则表达式.元字符应该只匹配除<CR><LF>之外的任何字符。如果文件中的最后一行未被<CR><LF>终止,则有一个错误允许它匹配End-Of-File。但是,.将不匹配空文件。

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

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

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

负面字符集似乎也是如此。像[^abc]这样的东西会匹配End-Of-File。像[abc]这样的正面角色似乎运作良好。我只在Win7上测试了这个。


6
投票

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

我还没有确认确切的条件或边界大小。我怀疑任何大于2GB的文件都可能存在风险。

我对此有过不同的经验,所以它不仅仅是文件大小。这看起来可能是FINDSTR hangs on XP and Windows 7 if redirected input does not end with LF的一个变种,但正如所展示的那样,当输入未被重定向时,这个特殊问题就会出现。

以下命令行会话(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文件以the way copy works终止。但请注意,此异常不会导致“小”文件出现问题。

通过额外的测试,我确认了以下内容:

  • 使用带有copy选项的/b用于二进制文件可防止添加0x1A字符,并且findstr不会挂在3GB文件上。
  • 使用不同的字符终止3GB文件也会导致findstr挂起。
  • 0x1A字符不会对“小”文件造成任何问题。 (与其他终止字符类似。)
  • CRLF解决问题后添加0x1A。 (LF本身就足够了。)
  • 使用type将文件传输到findstr工作而不会挂起。 (这可能是由于插入额外行尾的type|的副作用。)
  • 使用重定向输入<也会导致findstr挂起。但这是预期的;正如dbenham's post所解释的那样:“重定向输入必须以LF结尾”。

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是不同的;它不会将Stdin文件指针从其当前位置移开。例如,此代码在搜索行后插入一个新行:

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

我们可以借助于允许我们移动重定向文件的文件指针的辅助程序来充分利用此功能,如this example所示。

这种行为最初是由jebthis post报道的。


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

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

当这种形式的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
投票

我想在文件名中使用en dash( - )或em dash( - )时报告有关要在第一个答案中搜索的数据源部分的错误。

更具体地说,如果您要使用第一个选项 - 指定为参数的文件名,则找不到该文件。只要您使用选项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. 作为stdin通过重定向 我是一个带短划线的文件。
  3. 作为数据流来自管道 我是一个带短划线的文件。

带有em dash的文件名:

  1. 作为论点 FINDSTR:无法使用 - dash.txt打开文件名
  2. 作为stdin通过重定向 我是一个带破折号的文件。
  3. 作为数据流来自管道 我是一个带破折号的文件。

希望能帮助到你。

M.


-1
投票

/ D提示多个目录:将您的目录列表放在搜索字符串之前。这一切都有效:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.