Pourquoi findstr ne traite-t-il pas le dossier correctement (dans certaines circonstances)?

en écrivant des scripts récents dans cmd.exe, j'avais besoin d'utiliser findstr avec des expressions régulières - cmd standard requis par le client.commandes exe (pas de GnuWin32, ni Cygwin, ni VBS, ni Powershell).

je voulais juste savoir si une variable contenait des caractères majuscules et j'ai essayé d'utiliser:

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

quand %myvar% est défini à abc , qui en fait sort la chaîne et met errorlevel à 0, disant qu'une correspondance a été trouvée.

cependant, la variante complète:

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

ne pas sortie de la ligne et il définit correctement errorlevel à 1.

en outre:

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

fonctionne aussi comme prévu.

je manque évidemment quelque chose ici même si c'est seulement le fait que findstr est en quelque sorte cassé.

Pourquoi le premier (gamme) regex fonctionne pas dans ce cas?


Et encore plus "bizarre":

> 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]"

les deux derniers ci-dessus ne sortent pas non plus la chaîne!!

14
demandé sur paxdiablo 2010-04-14 11:56:09

4 réponses

je crois que c'est surtout un horrible défaut de conception.

nous nous attendons tous à ce que les fourchettes se fondent sur la valeur du code ASCII. Mais ils ne le font pas - au lieu de cela les gammes sont basées sur une séquence de collation qui correspond presque à la séquence par défaut utilisée par Tri. EDIT -la séquence de collation exacte utilisée par FINDSTR est maintenant disponible à https://stackoverflow.com/a/20159191/1012053 en vertu de la section intitulée Regex classe de personnage intervalle [x-y] .

j'ai préparé un fichier texte contenant une ligne pour chaque caractère ASCII étendu de 1 - 255, excluant 10 (LF), 13 (CR), et 26 (EOF sur Windows). Sur chaque ligne j'ai le caractère, suivi d'un espace, suivi du code décimal pour le caractère. J'ai ensuite lancé le fichier dans le système de tri et j'ai saisi la sortie dans une barre sorted.fichier txt.

je peux maintenant testez facilement n'importe quelle gamme regex par rapport à ce fichier trié et démontrez comment la gamme est déterminée par une séquence de collation qui est presque la même que 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

les résultats ne sont pas tout à fait ce que nous nous attendions à ce que les char 171, 172 et 253 soient jetés dans le mix. Mais les résultats sont parfaitement sensés. Le préfixe du numéro de ligne correspond à la séquence de tri collation, et vous pouvez voir que la gamme correspond exactement à la séquence de tri.

voici un autre test de distance qui suit exactement la séquence de tri:

>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

Il y a une petite anomalie avec des caractères alphanumériques. Le caractère " a "trie entre" A "et" Z " mais il ne correspond pas [A-Z]. "z" trie après "Z", mais il correspond [A-Z]. Il y a un problème correspondant avec [A-z]. "A" sort avant "a", mais il correspond [a-z]. "Z" se situe entre "a" et "z", mais ne correspond pas à [A-z].

Voici les résultats [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

et les résultats [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

trie les majuscules avant les minuscules. (EDIT - je viens de lire l'aide pour le TRI et appris qu'il ne fait pas de distinction entre les majuscules et les minuscules. Le fait que ma sortie de tri a toujours mis supérieur avant inférieur est probablement un résultat de l'ordre de l'entrée.) regex Mais apparemment, sortes de minuscules avant de les majuscules. Toutes les gammes suivantes ne correspondent à aucune caractère.

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

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

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

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

inversant l'ordre trouve les caractères.

>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

il y a des caractères supplémentaires que regex trie différemment de SORT, mais je n'ai pas de liste précise.

14
répondu dbenham 2017-05-23 12:33:48

donc si vous voulez

  • seuls les numéros: FindStr /R "^[0123-9]*$"

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

  • hexadécimal: FindStr /R "^[0123-9aAb-Cd-EfF]*$"

  • alpha sans accent: FindStr /R "^[aAb-Cd-EfFg-Ij-NoOp-St-Uv-YzZ]*$"

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

5
répondu JLGautier 2015-12-10 17:03:28

cela semble être causé par l'utilisation de plages dans les recherches d'expressions régulières.

il ne se produit pas pour le premier caractère dans la gamme. Il ne se produit pas du tout pour les non-gammes.

> 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]"

selon le SS64 CMD FINDSTR page (qui, dans une étonnante démonstration de circularité, renvoie à cette question), la gamme [A-Z] :

... inclut l' Alphabet anglais, en majuscules et en minuscules (à l'exception de "a"), ainsi que des caractères alphabétiques Non-anglais avec des signes diacritiques.

Pour contourner le problème, dans mon environnement, j'ai simplement utilisé spécifiques expressions régulières (comme [ABCD] plutôt que [A-D] ). Une approche plus raisonnable pour ceux qui sont autorisés serait de télécharger CygWin ou GnuWin32 et d'utiliser grep de l'un de ces paquet.

3
répondu paxdiablo 2015-07-15 11:42:58

tout le monde au-dessus a tort. L'ordre d'alpha char est le suivant: aAbBcCdDeE..zZ donc echo a | findstr /r "[A-Z]" ne renvoie rien, puisque a est en dehors de cette plage.

echo abc|findstr /r "[A-Z][A-Z][A-Z]" ne renvoie rien non plus, puisque le premier rang correspond à b , le second à c et le troisième à rien ne correspond à rien et donc l'ensemble du motif regex ne trouve rien.

si vous aimez correspondre à n'importe quel caractère de l'alphabet latin - utilisez [a-Z] .

-1
répondu no kudos 2015-07-15 11:20:20