为什么findstr不能正确处理案件(在某些情况下)?

问题描述:

在cmd.exe中编写一些最新的脚本时,我需要使用findstr以及正则表达式 - 客户需要的标准cmd.exe命令(无GnuWin32,Cygwin,VBS或Powershell)。为什么findstr不能正确处理案件(在某些情况下)?

我只是想知道,如果一个变量包含任何大写字符,并尝试使用:

> set myvar=abc 
> echo %myvar%|findstr /r "[A-Z]" 
abc 
> echo %errorlevel% 
0 

%myvar%设置为abc,实际输出字符串,并设置errorlevel为0,说一场比赛被发现。

然而,全名单变种:

> echo %myvar%|findstr /r "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]" 
> echo %errorlevel% 
1 

输出线并正确设置errorlevel为1

另外:

> echo %myvar%|findstr /r "^[A-Z]*$" 
> echo %errorlevel% 
1 

也适用如预期。

我很明显缺少东西这里即使它只是findstr在某种程度上被打破的事实。

为什么第一个(范围)正则表达式在这种情况下不起作用?


并且还更古怪:

> echo %myvar%|findstr /r "[A-Z]" 
abc 
> echo %myvar%|findstr /r "[A-Z][A-Z]" 
abc 
> echo %myvar%|findstr /r "[A-Z][A-Z][A-Z]" 
> echo %myvar%|findstr /r "[A]" 

最后两个也不会输出字符串以上!

+0

以及FINDSTR的帮助显示/ I开关设置不区分大小写的模式,但我不能让FINDSTR是大小写敏感的,无论我用什么样的范围内,太! – Axarydax 2010-04-14 08:05:07

+0

在我最初的错误开始后,我只能第二次(或第三次)两次观察。您已经为findstr中的某个bug显示了解决方法...使用完整列表变体。 – 2010-04-14 08:54:25

+0

只是一个注释:'echo%myvar%| findstr/r'^ [AZ] * $“'实际上并不工作,如果将''^ [AZ] * $”'更改为'abc' '“^ [AZ] * $”',它仍然会输出'abc',如[AZ]中所示,并且错误级别为0 – YOU 2010-04-14 10:12:52

我相信这是一个可怕的设计缺陷。

我们都希望根据ASCII码值来整理范围。但它们不是 - 而是范围基于排序顺序,几乎匹配SORT使用的默认顺序。EDIT通过FINDSTR使用-The确切归类序列现在可以在https://*.com/a/20159191/1012053下标题的Regex字符类范围[X-Y]部分。

我准备了一个文本文件,其中包含1到255的每个扩展ASCII字符的一行,不包括10(LF),13(CR)和26(EOF在Windows上)。 在每行上我都有字符,后跟一个空格,后面跟着字符的十进制代码。然后我通过SORT运行该文件,并在sortedChars.txt文件中捕获输出。

我现在可以很容易地测试任何正则表达式范围对这个排序文件,并演示范围是如何通过与SORT几乎相同的排序顺序来确定的。

>findstr /nrc:"^[0-9]" sortedChars.txt 
137:0 048 
138:½ 171 
139:¼ 172 
140:1 049 
141:2 050 
142:² 253 
143:3 051 
144:4 052 
145:5 053 
146:6 054 
147:7 055 
148:8 056 
149:9 057 

结果并不完全符合我们的预期,字符171,172和253被引入混合。但结果非常合理。行号前缀对应于SORT归类序列,您可以根据SORT序列看到范围完全匹配。

下面是恰好跟随SORT序列另一个范围测试:

>findstr /nrc:"^[!-=]" sortedChars.txt 
34:! 033 
35:" 034 
36:# 035 
37:$ 036 
38:% 037 
39:& 038 
40:(040 
41:) 041 
42:* 042 
43:, 044 
44:. 046 
45:/ 047 
46:: 058 
47:; 059 
48:? 063 
49:@ 064 
50:[ 091 
51:\ 092 
52:] 093 
53:^ 094 
54:_ 095 
55:` 096 
56:{ 123 
57:| 124 
58:} 125 
59:~ 126 
60:¡ 173 
61:¿ 168 
62:¢ 155 
63:£ 156 
64:¥ 157 
65:₧ 158 
66:+ 043 
67:∙ 249 
68:< 060 
69:= 061 

有一个小的异常与字母字符。字符“a”在“A”和“Z”之间排序,但它不匹配[A-Z]。 “z”在“Z”之后排序,但它匹配[A-Z]。 [a-z]有相应的问题。 “A”在“a”之前排序,但与[a-z]匹配。 “Z”在“a”和“z”之间排序,但与[a-z]不匹配。

下面是[A-Z]结果:

>findstr /nrc:"^[A-Z]" sortedChars.txt 
151:A 065 
153:â 131 
154:ä 132 
155:à 133 
156:å 134 
157:Ä 142 
158:Å 143 
159:á 160 
160:ª 166 
161:æ 145 
162:Æ 146 
163:B 066 
164:b 098 
165:C 067 
166:c 099 
167:Ç 128 
168:ç 135 
169:D 068 
170:d 100 
171:E 069 
172:e 101 
173:é 130 
174:ê 136 
175:ë 137 
176:è 138 
177:É 144 
178:F 070 
179:f 102 
180:ƒ 159 
181:G 071 
182:g 103 
183:H 072 
184:h 104 
185:I 073 
186:i 105 
187:ï 139 
188:î 140 
189:ì 141 
190:í 161 
191:J 074 
192:j 106 
193:K 075 
194:k 107 
195:L 076 
196:l 108 
197:M 077 
198:m 109 
199:N 078 
200:n 110 
201:ñ 164 
202:Ñ 165 
203:ⁿ 252 
204:O 079 
205:o 111 
206:ô 147 
207:ö 148 
208:ò 149 
209:Ö 153 
210:ó 162 
211:º 167 
212:P 080 
213:p 112 
214:Q 081 
215:q 113 
216:R 082 
217:r 114 
218:S 083 
219:s 115 
220:ß 225 
221:T 084 
222:t 116 
223:U 085 
224:u 117 
225:û 150 
226:ù 151 
227:ú 163 
228:ü 129 
229:Ü 154 
230:V 086 
231:v 118 
232:W 087 
233:w 119 
234:X 088 
235:x 120 
236:Y 089 
237:y 121 
238:ÿ 152 
239:Z 090 
240:z 122 

而[A-Z]导致

>findstr /nrc:"^[a-z]" sortedChars.txt 
151:A 065 
152:a 097 
153:â 131 
154:ä 132 
155:à 133 
156:å 134 
157:Ä 142 
158:Å 143 
159:á 160 
160:ª 166 
161:æ 145 
162:Æ 146 
163:B 066 
164:b 098 
165:C 067 
166:c 099 
167:Ç 128 
168:ç 135 
169:D 068 
170:d 100 
171:E 069 
172:e 101 
173:é 130 
174:ê 136 
175:ë 137 
176:è 138 
177:É 144 
178:F 070 
179:f 102 
180:ƒ 159 
181:G 071 
182:g 103 
183:H 072 
184:h 104 
185:I 073 
186:i 105 
187:ï 139 
188:î 140 
189:ì 141 
190:í 161 
191:J 074 
192:j 106 
193:K 075 
194:k 107 
195:L 076 
196:l 108 
197:M 077 
198:m 109 
199:N 078 
200:n 110 
201:ñ 164 
202:Ñ 165 
203:ⁿ 252 
204:O 079 
205:o 111 
206:ô 147 
207:ö 148 
208:ò 149 
209:Ö 153 
210:ó 162 
211:º 167 
212:P 080 
213:p 112 
214:Q 081 
215:q 113 
216:R 082 
217:r 114 
218:S 083 
219:s 115 
220:ß 225 
221:T 084 
222:t 116 
223:U 085 
224:u 117 
225:û 150 
226:ù 151 
227:ú 163 
228:ü 129 
229:Ü 154 
230:V 086 
231:v 118 
232:W 087 
233:w 119 
234:X 088 
235:x 120 
236:Y 089 
237:y 121 
238:ÿ 152 
240:z 122 

排序排序小写之前大写。 (编辑 - 我只是读了SORT的帮助,并了解到它不区分大写和小写。事实上,我的SORT输出始终低于上一个可能是输入顺序的结果。)但是,正则表达式在大写之前显然是小写。以下所有范围都无法匹配任何字符。

>findstr /nrc:"^[A-a]" sortedChars.txt 

>findstr /nrc:"^[B-b]" sortedChars.txt 

>findstr /nrc:"^[C-c]" sortedChars.txt 

>findstr /nrc:"^[D-d]" sortedChars.txt 

颠倒顺序查找字符。

>findstr /nrc:"^[a-A]" sortedChars.txt 
151:A 065 
152:a 097 

>findstr /nrc:"^[b-B]" sortedChars.txt 
163:B 066 
164:b 098 

>findstr /nrc:"^[c-C]" sortedChars.txt 
165:C 067 
166:c 099 

>findstr /nrc:"^[d-D]" sortedChars.txt 
169:D 068 
170:d 100 

还有其他的字符,正则表达式排序不同于排序,但我还没有一个确切的清单。

+0

由于社区现在重视你的答案比我的更高(并且,让我们面对它,这是一个更好的答案,更多的解释为什么会发生这种情况),我决定改变这个答案。 – paxdiablo 2012-01-14 01:23:28

这似乎是由正则表达式搜索中使用范围引起的。

对于范围中的第一个字符不会发生。对于非范围它根本不会发生。

> echo a | findstr /r "[A-C]" 
> echo b | findstr /r "[A-C]" 
    b 
> echo c | findstr /r "[A-C]" 
    c 
> echo d | findstr /r "[A-C]" 
> echo b | findstr /r "[B-C]" 
> echo c | findstr /r "[B-C]" 
    c 

> echo a | findstr /r "[ABC]" 
> echo b | findstr /r "[ABC]" 
> echo c | findstr /r "[ABC]" 
> echo d | findstr /r "[ABC]" 
> echo b | findstr /r "[BC]" 
> echo c | findstr /r "[BC]" 

> echo A | findstr /r "[A-C]" 
    A 
> echo B | findstr /r "[A-C]" 
    B 
> echo C | findstr /r "[A-C]" 
    C 
> echo D | findstr /r "[A-C]" 

按照SS64 CMD FINDSTR page(在圆的一个惊人的显示,参考这个问题),该范围[A-Z]

...包括完整的英文字母,大写和小写(除了“a”),以及非英语字母与变音符号。

为了解决在我的环境问题,我只是用特定的正则表达式(如[ABCD]而非[A-D])。对于那些被允许的人来说,更明智的做法是下载CygWinGnuWin32,并从其中一个包中使用grep

以上所有人都是错的。 alpha字符顺序是follwoing:aAbBcCdDeE..zZ 所以echo a | findstr /r "[A-Z]"返回什么都没有,因为a超出该范围。

echo abc|findstr /r "[A-Z][A-Z][A-Z]"也不返回任何内容,因为第一范围组匹配b,第二个匹配c,第三个匹配任何内容,因此整个正则表达式模式找不到任何内容。

如果您想匹配拉丁字母的任何字符 - 请使用[a-Z]

+0

这与我在回答中所说的没有什么不同:*“但是正则表达式在大写之前显然是小写。”*。在我的调查过程中,我错误地认为SORT命令排序在较低之前,但后来我承认这是一个错误 - SORT不区分与正则表达式排序顺序完全无关的情况。确切的正则表达式归类序列可在http://*.com/a/8844873/1012053获取 – dbenham 2015-10-11 22:26:41

所以,如果你想

  • 只有数字:FindStr /R "^[0123-9]*$"

  • 八:FindStr /R "^[0123-7]*$"

  • 十六进制:FindStr /R "^[0123-9aAb-Cd-EfF]*$"

  • 阿尔法没有重音:FindStr /R "^[aAb-Cd-EfFg-Ij-NoOp-St-Uv-YzZ]*$"

  • 字母:FindStr /R "^[0123-9aAb-Cd-EfFg-Ij-NoOp-St-Uv-YzZ]*$"