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

cmd.exe中编写一些最新的脚本时,我需要使用findstr正则expression式 – 客户需要标准的cmd.exe命令(不包括GnuWin32,Cygwin,VBS和Powershell)。

我只是想知道一个variables是否包含任何大写字母,并试图使用:

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

%myvar%设置为abc时,实际输出string并将errorlevel设置为0,表示find了匹配项。

但是,全名列表:

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

不输出该行,并正确地将errorlevel设置为1。

此外:

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

也按预期工作。

我明显在这里丢失了一些东西 ,即使这只是findstr被破坏的事实。

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


更奇怪的是:

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

上面的最后两个也不输出string!

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

我们都希望根据ASCII码值来整理范围。 但是它们不是 – 而是范围基于排序顺序,几乎匹配SORT使用的默认顺序。 编辑 – FINDSTR使用的确切排序顺序现在可在https://stackoverflow.com/a/20159191/1012053在标题为正则表达式字符类范围[xy]部分

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

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

 >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”之间排序,但不匹配[AZ]。 “z”在“Z”之后排序,但它匹配[AZ]。 有一个相应的问题[az]。 “A”在“a”之前排序,但匹配[az]。 “Z”在“a”和“z”之间排序,但不匹配[az]。

这是[AZ]结果:

 >findstr /nrc:"^[AZ]" 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 

和[az]的结果

 >findstr /nrc:"^[az]" 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的帮助,并得知它不区分大写和小写。事实上,我的排序输出始终高于之前较低可能是输入的顺序的结果。)但正则表达式显然排序小写在大写之前。 以下所有范围都不能匹配任何字符。

 >findstr /nrc:"^[Aa]" sortedChars.txt >findstr /nrc:"^[Bb]" sortedChars.txt >findstr /nrc:"^[Cc]" sortedChars.txt >findstr /nrc:"^[Dd]" sortedChars.txt 

反转订单查找字符。

 >findstr /nrc:"^[aA]" sortedChars.txt 151:A 065 152:a 097 >findstr /nrc:"^[bB]" sortedChars.txt 163:B 066 164:b 098 >findstr /nrc:"^[cC]" sortedChars.txt 165:C 067 166:c 099 >findstr /nrc:"^[dD]" sortedChars.txt 169:D 068 170:d 100 

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

所以,如果你想

  • 只有数字: 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 a | findstr /r "[AC]" > echo b | findstr /r "[AC]" b > echo c | findstr /r "[AC]" c > echo d | findstr /r "[AC]" > echo b | findstr /r "[BC]" > echo c | findstr /r "[BC]" 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 "[AC]" A > echo B | findstr /r "[AC]" B > echo C | findstr /r "[AC]" C > echo D | findstr /r "[AC]" 

根据SS64 CMD FINDSTR页面 (其中圆形的惊人的显示,引用这个问题),范围[AZ]

…包括完整的英文字母,包括大写和小写(“a”除外),以及带有变音符号的非英文字母字符。

为了解决环境中的问题,我简单地使用了特定的正则表达式(比如[ABCD]而不是[AD] )。 对于那些被允许的,更明智的做法是下载CygWin或者GnuWin32,并从这些软件包中使用grep

以上所有人都是错的。 alpha字符顺序如下: aAbBcCdDeE..zZ echo a | findstr /r "[AZ]" echo a | findstr /r "[AZ]"返回任何内容,因为a在该范围之外。

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

如果你想匹配拉丁字母的任何字符 – 使用[aZ]