Windows 为什么findstr不能正确处理案例(在某些情况下)?
在用cmd.exe编写一些最新脚本时,我需要将Windows 为什么findstr不能正确处理案例(在某些情况下)?,windows,regex,batch-file,cmd,findstr,Windows,Regex,Batch File,Cmd,Findstr,在用cmd.exe编写一些最新脚本时,我需要将findstr与正则表达式一起使用-客户需要的标准cmd.exe命令(没有GnuWin32、Cygwin、VBS或Powershell) 我只是想知道变量是否包含任何大写字符,并试图使用: > set myvar=abc > echo %myvar%|findstr /r "[A-Z]" abc > echo %errorlevel% 0 当%myvar%设置为abc时,实际输出字符串并将errorlevel设置为0,表示找到了匹
findstr
与正则表达式一起使用-客户需要的标准cmd.exe命令(没有GnuWin32、Cygwin、VBS或Powershell)
我只是想知道变量是否包含任何大写字符,并试图使用:
> 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]"
上面的最后两个也不输出字符串 这似乎是由于在正则表达式搜索中使用范围造成的 对于范围中的第一个字符,它不会出现。对于非范围,它根本不会发生
> 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]"
根据(在令人惊叹的圆形显示中,它引用了这个问题),范围[a-Z]
:
。。。包括完整的英文字母表,包括大写和小写字母(a除外),以及带有变音符号的非英文字母
为了在我的环境中解决这个问题,我只使用了特定的正则表达式(例如
[ABCD]
,而不是[A-D]
)。对于那些被允许的人来说,一个更明智的方法是从其中一个软件包下载或使用grep。我认为这主要是一个可怕的设计缺陷
我们都希望根据ASCII码值整理范围。但是它们没有-相反,范围基于排序规则序列,该序列几乎与SORT使用的默认序列匹配编辑-FINDSTR使用的精确排序顺序现在可在标题为正则表达式字符类范围[x-y]的部分中找到
我准备了一个文本文件,其中1-255之间的每个扩展ASCII字符包含一行,不包括10(LF)、13(CR)和26(Windows上的EOF)。
每行我都有一个字符,后跟一个空格,后跟该字符的十进制代码。然后,我通过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号木炭被放入混合料中。但结果完全有道理。行号前缀对应于排序排序规则序列,您可以看到范围根据排序序列完全匹配
下面是另一个严格遵循排序顺序的范围测试:
>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-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
排序将大写字母排序在小写字母之前。(编辑-我刚刚阅读了排序帮助,了解到它不区分大写和小写。我的排序输出始终将大写放在小写之前这一事实可能是输入顺序的结果。)但正则表达式显然是将小写排序在大写之前。以下所有范围都无法匹配任何字符
>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
颠倒顺序查找字符
>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
regex对其他字符的排序与SORT不同,但我没有一个精确的列表。上面的每个人都错了。
字母字符顺序如下:aAbBcCdDeE..zZ
因此echo a | findstr/r“[a-Z]”
不返回任何内容,因为a
超出了该范围
echo abc | findstr/r“[A-Z][A-Z][A-Z]”
也不返回任何内容,因为第一个范围组匹配b
,第二个范围组匹配c
,而第三个范围组不匹配任何内容,因此整个正则表达式模式没有找到任何内容
如果您想匹配拉丁字母表中的任何字符,请使用[a-Z]
- 仅数字:
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]*$”
echo%myvar%| findstr/r“^[a-Z]*$”
实际上不起作用,在abc
之后有空格,如果您将“^[a-Z]*$”
更改为“^[a-Z]*$”
,它仍会像“[a-Z]”一样输出abc
,并且错误级别为0,实际上这可能是另一个bug,@S.Mark,模式“^[A-Z]*$
(有很多前导空格)给出了相同的结果,如果将输出捕获到文件中,则没有空格。我刚刚遇到了这个问题;感谢解决方案(解决方法)。这里还有一点额外的信息:[A-Z]也可以找到重音字符(在ANSI编码的文件中,而不是Unicode)。因此,这个错误可能是由试图支持修饰字符的代码引起的。因为社区现在认为你的答案比我的答案更重要(而且,让我们面对现实,这也是一个更好的答案,并更多地解释了为什么会发生这种情况),我决定把大家接受的答案改成这个。这和我在回答中说的没什么两样:“但是regex ap