200

Windows FINDSTR 命令的文档非常糟糕。可以通过FINDSTR /?, 或获得非常基本的命令行帮助HELP FINDSTR,但它还远远不够。在https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr上有更多的在线文档。

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

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

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

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

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

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

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

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

4

8 回答 8

298

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

FINDSTR 输出
文档从不费心解释 FINDSTR 的输出。它暗示了打印匹配行的事实,但仅此而已。

匹配行输出格式如下:

文件名:lineNumber:lineOffset:文本

在哪里

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

注意 - 在搜索多个文件时,可以避免使用非标准(且记录不充分)通配符 <>. 可以在此处找到有关这些通配符如何工作的确切规则。最后,您可以查看非标准通配符如何与 FINDSTR 一起使用的示例

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

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

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

FINDSTR "^" FILE >FILE_COPY

/A 选项仅设置 fileName:、lineNumber: 和 lineOffset: 输出的颜色。匹配行的文本始终以当前控制台颜色输出。/A 选项仅在输出直接显示到控制台时才有效。如果输出被重定向到文件或管道,则 /A 选项无效。有关将输出重定向到 CON 时错误行为的描述,请参阅Aacini 的答案中的 2018-08-18 编辑。

大多数控制字符和许多扩展 ASCII 字符在 XP 上显示为点
FINDSTR 在 XP 上将来自匹配行的大多数不可打印控制字符显示为屏幕上的点(句点)。以下控制字符是例外;它们显示为自己:0x09 Tab、0x0A LineFeed、0x0B Vertical Tab、0x0C Form Feed、0x0D Carriage Return。

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(错误)

要搜索的数据源 (根据 Windows 7 测试更新)
Findstr 只能从以下来源之一搜索数据:

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

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

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

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

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

搜索字符串的来源根据 Windows 7 测试更新)
和选项可以组合。可以指定多个选项。如果指定了多个选项,则只使用最后一个。如果使用or ,则所有非选项参数都被假定为要搜索的文件。如果既不使用也不使用,则第一个非选项参数被视为以空格分隔的搜索词列表。/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 命令的行为一致。

但是/Dand/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 不会改变重定向输入。

如果重定向输入不以结尾,FINDSTR 在 XP 和 Windows 7 上挂起<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 来测试)。

选项语法
选项字母不区分大小写,因此/i/I是等价的。

选项可以带有前缀/或者- 选项可以在单个/或之后连接-。但是,连接的选项列表最多可以包含一个多字符选项,例如 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"

选项也可能被引用。所以/i, -i,"/i""-i"都是等价的。同样,、/c:string和都是等价的。"/c":string"/c:"string"/c:string"

如果搜索字符串以/or-文字开头,则必须使用/Cor选项。/G感谢Stephan在评论中报告此问题(已删除)。

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

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

在 Windows XP 上,搜索字符串的长度显然更短。Findstr 错误:“搜索字符串太长”:如何在“for”循环中提取和匹配子字符串? 对于文字和正则表达式搜索,XP 限制为 127 个字节。

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

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

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

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

/G:file- 默认值取决于文件中第一个非空行的内容。如果第一个搜索字符串是包含至少一个未转义元字符的有效正则表达式,则所有搜索字符串都被视为正则表达式。否则,所有搜索字符串都被视为文字。

建议 - 使用时始终明确指定/L文字选项或/R正则表达式选项"string argument"or /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:正则表达式中的反斜杠始终可以表示为[\\]. 它通常可以表示为\\。但是如果反斜杠在转义引号之前,这永远不会起作用。

    转义引号前的一个或多个反斜杠必须进行双重转义,或者编码为[\\]

    • \"可以编码为\\\\\"[\\]\"
    • \\"可以编码为\\\\\\\\\"[\\][\\]\"\\[\\]\"

在 /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)并使用 /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 部分继续......

于 2012-01-13T01:40:09.500 回答
70

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

有限的正则表达式 (regex) 支持
FINDSTR 对正则表达式的支持极为有限。如果 HELP 文档中没有,则不支持。

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

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

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

注意 - 如前所述,通过管道传输和重定向到 FINDSTR 的输入可能已<CR><LF>附加在源文件中。显然,这会影响使用$.

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

位置选项 /B /E /X
位置选项的作用与 and 相同^$除了它们也适用于文字搜索字符串。

^/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]可以匹配 End-Of-File
正则表达式.元字符应该只匹配除<CR>or之外的任何字符<LF>。如果文件中的最后一行不是由<CR>or终止,则存在一个允许它匹配 End-Of-File 的错误<LF>。但是,.不会匹配空文件。

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

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

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

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

于 2013-11-23T06:03:30.337 回答
8

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

< 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%"
于 2015-02-02T13:17:38.933 回答
7

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

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

我对此有不同的经历,所以它不仅仅是文件大小。如果重定向的输入不以 LF 结尾,这看起来可能是在 XP 和 Windows 7 上挂起的 FINDSTR 的变体,但正如所示,当输入重定向时,此特定问题就会显现。

以下命令行会话 (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 文件也会导致 afindstr挂起。
  • 0x1A字符不会对“小”文件造成任何问题。(对于其他终止字符也是如此。)
  • 添加CRLF0x1A解决问题。(LF本身可能就足够了。)
  • 用于将文件通过type管道传输到findstr作品中而无需挂起。type(这可能是由于其中一个或|插入一个额外的行尾的副作用。)
  • 使用重定向输入<也会导致findstr挂起。但这是意料之中的;正如dbenham 的帖子中所解释的那样:“重定向的输入必须以LF结尾。
于 2014-04-08T16:34:56.863 回答
2

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

更具体地说,如果您要使用第一个选项 -指定为参数的文件名,将找不到该文件。只要您使用选项 2 - stdin via redirection或 3 - data stream from a pipe, 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。

于 2015-03-22T11:36:55.703 回答
2

FINDSTR 有一个我在https://superuser.com/questions/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 转义颜色代码的变量)。

我最初的解决方案是在 FINDSTR 之后调用一个无操作子例程。不知何故,调用或返回“重置”了需要重置的任何内容。

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

于 2020-04-09T13:53:12.467 回答
2

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

  • 0当在所有指定文件的一行中至少遇到一个匹配项时;
  • 1否则;

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

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

这意味着该/V选项也会更改返回的ErrorLevel,但它不仅仅是还原它!

例如,当您有一个test.txt包含两行的文件时,其中一行包含字符串text,而另一行不包含,两者都findstr "text" "test.txt"返回findstr /V "text" "test.txt"一个ErrorLevelof 0

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

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

(为了完整起见:该find命令/V的行为方式与选项和完全相同ErrorLevel;该/C选项不影响ErrorLevel。)

于 2019-09-17T21:33:58.340 回答
-1

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

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

正如预期的那样,如果您不以\. "如果目录名称中没有空格,则用 包围路径是可选的。结尾\是可选的。location 的输出将包括您提供的任何路径。无论是否使用".

于 2015-01-22T20:11:26.393 回答