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

时间:2012-01-13 01:39:15

标签: batch-file cmd findstr

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

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

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

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

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

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

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

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

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

7 个答案:

答案 0 :(得分:60)

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

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

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

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

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

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

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

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

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

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

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

正则表达式字边界
\<必须是正则表达式中的第一个术语。如果任何其他字符在它之前,则正则表达式将不匹配任何内容。 \<对应于输入的最开始,一行的开始(紧跟在&lt; LF&gt;之后的位置),或紧跟在任何&#34;非单词&#34;之后的位置。字符。下一个角色不一定是&#34;字&#34;字符。

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

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

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]包括完整的英文字母,包括大写和小写(&#34; a&#34;除外),以及带有变音符号的非英文字母字符。

下面是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弹出窗口显示&#34;查找字符串(QGREP)实用程序遇到问题并需要关闭。对于给您带来的不便,我们深表歉意。&#34; 根据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不会挂起,但它始终无法找到匹配项,偶尔会打印以下错误消息 - &#34;该过程尝试写入不存在的管道。&#34;

我无法访问Vista计算机,因此我无法在Vista上进行测试。

正则表达式错误:.[^anySet]可以匹配文件结尾
正则表达式.元字符应仅匹配<CR><LF>以外的任何字符。如果文件中的最后一行未被<CR><LF>终止,则存在允许其与文件结尾匹配的错误。但是,.与空文件不匹配。

例如,名为&#34; test.txt&#34;的文件在不终止x<CR>的情况下,包含一行<LF>符合以下内容:

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

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

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

答案 1 :(得分:5)

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

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

我对此有过不同的经验,所以它不仅仅是文件大小。这似乎可能是FINDSTR hangs on XP and Windows 7 if redirected input does not end with LF的变体,但正如所示,当输入重定向时,此特定问题就会显现。

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

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终止。唯一的异常是由于the way copy works,文件以0x1A终止。但请注意,此异常 不会导致“小”文件出现问题

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

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

答案 2 :(得分:5)

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

< 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所示。

此行为最初由jeb this 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%"

答案 3 :(得分:2)

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

更具体地说,如果您要使用第一个选项 - 文件名指定为参数,则无法找到该文件。只要您使用选项2 - stdin via redirection 或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. 作为stdin通过重定向
    我是一个带短划线的文件。

  4. 作为来自管道的数据流
    我是一个带短划线的文件。

  5. 带有短划线的文件名:

    1. 作为论点 FINDSTR:无法使用 - dash.txt

    2. 打开文件名
    3. 作为stdin通过重定向
      我是带有短划线的文件。

    4. 作为来自管道的数据流
      我是带有短划线的文件。

    5. 希望它有所帮助。

      微米。

答案 4 :(得分: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转义颜色代码的var)。

我最初的解决方法是在FINDSTR之后调用空操作子程序。无论如何,无论是调用还是返回“重置”都需要重置。

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

答案 5 :(得分:1)

假设没有无效或不兼容的开关,并且没有搜索字符串超出适用的长度限制,则findstr command会将ErrorLevel (or exit code)设置为以下值之一:

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

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

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

这意味着/V选项也更改了返回的ErrorLevel,但是只是将其还原!

例如,当您有一个包含两行的文件test.txt时,其中之一包含字符串text,而另一行则不包含字符串,findstr "text" "test.txt"和{{1} }返回findstr /V "text" "test.txt"中的ErrorLevel

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

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

(出于完整性考虑,find command的行为与ErrorLevel选项和/V完全相同; ErrorLevel选项不影响{ {1}}。)

答案 6 :(得分:-1)

多个目录的

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

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

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