batch file exemple Quelles sont les fonctionnalités non documentées et les limitations de la commande Windows FINDSTR?




findstr exemple (5)

La commande Windows FINDSTR est horriblement documentée. L'aide en ligne de commande très basique est disponible via FINDSTR /? , ou HELP FINDSTR , mais c'est terriblement insuffisant. Il y a un peu plus de documentation en ligne à http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/findstr.mspx?mfr=true .

Il existe de nombreuses fonctionnalités et limitations de FINDSTR qui ne sont même pas indiquées dans la documentation. Ils ne peuvent pas non plus être anticipés sans connaissances préalables et / ou expérimentation prudente.

Donc la question est - Quelles sont les fonctionnalités et les limitations de FINDSTR non documentées?

Le but de cette question est de fournir un référentiel à guichet unique des nombreuses fonctionnalités non documentées afin que:

A) Les développeurs peuvent tirer pleinement parti des fonctionnalités qui sont là.

B) Les développeurs ne perdent pas leur temps à se demander pourquoi quelque chose ne fonctionne pas quand il semble que ce devrait être le cas.

Veuillez vous assurer de connaître la documentation existante avant de répondre. Si l'information est couverte par l'AIDE, elle n'appartient pas ici.

Ce n'est pas non plus un endroit pour montrer des utilisations intéressantes de FINDSTR. Si une personne logique peut anticiper le comportement d'un usage particulier de FINDSTR en fonction de la documentation, alors cela n'appartient pas ici.

Dans le même ordre d'idée, si une personne logique peut anticiper le comportement d'un usage particulier en fonction d'informations contenues dans des réponses existantes, alors, encore une fois, cela n'appartient pas ici.


Answer #1

/D tip for multiple directories: put your directory list before the search string. These all work:

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

As expected, the path is relative to location if you don't start the directories with \ . Surrounding the path with " is optional if there are no spaces in the directory names. The ending \ is optional. The output of location will include whatever path you give it. It will work with or without surrounding the directory list with " .


Answer #2

findstr sometimes hangs unexpectedly when searching large files.

I haven't confirmed the exact conditions or boundary sizes. I suspect any file larger 2GB may be at risk.

I have had mixed experiences with this, so it is more than just file size. This looks like it may be a variation on FINDSTR hangs on XP and Windows 7 if redirected input does not end with LF , but as demonstrated this particular problem manifests when input is not redirected.

The following command line session (Windows 7) demonstrates how findstr can hang when searching a 3GB file.

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>

Note, I've verified in a hex editor that all lines are terminated with CRLF . The only anomaly is that the file is terminated with 0x1A due to the way copy works . Note however, that this anomaly doesn't cause a problem on "small" files .

With additional testing I have confirmed the following:

  • Using copy with the /b option for binary files prevents the addition of the 0x1A character, and findstr doesn't hang on the 3GB file.
  • Terminating the 3GB file with a different character also causes a findstr to hang.
  • The 0x1A character doesn't cause any problems on a "small" file. (Similarly for other terminating characters.)
  • Adding CRLF after 0x1A resolves the problem. ( LF by itself would probably suffice.)
  • Using type to pipe the file into findstr works without hanging. (This might be due to a side effect of either type or | that inserts an additional End Of Line.)
  • Use redirected input < also causes findstr to hang. But this is expected; as explained in dbenham's post : "redirected input must end in LF " .

Answer #3

When several commands are enclosed in parentheses and there are redirected files to the whole block:

< input.txt (
   command1
   command2
   . . .
) > output.txt

... then the files remains open as long as the commands in the block be active, so the commands may move the file pointer of the redirected files. Both MORE and FIND commands move the Stdin file pointer to the beginning of the file before process it, so the same file may be processed several times inside the block. For example, this code:

more < input.txt >  output.txt
more < input.txt >> output.txt

... produce the same result than this one:

< input.txt (
   more
   more
) > output.txt

Ce code:

find    "search string" < input.txt > matchedLines.txt
find /V "search string" < input.txt > unmatchedLines.txt

... produce the same result than this one:

< input.txt (
   find    "search string" > matchedLines.txt
   find /V "search string" > unmatchedLines.txt
)

FINDSTR is different; it does not move the Stdin file pointer from its current position. For example, this code insert a new line after a search line:

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

We may make good use of this feature with the aid of an auxiliary program that allow us to move the file pointer of a redirected file, as shown in this example .

This behavior was first reported by jeb at this post .


Answer #4

La réponse a continué de la partie 1 ci - dessus - J'ai rencontré la limite de 30 000 caractères :-(

Support d'expressions régulières limitées (regex)
Le support FINDSTR pour les expressions régulières est extrêmement limité. Si ce n'est pas dans la documentation HELP, il n'est pas supporté.

Au-delà de cela, les expressions regex qui sont supportées sont implémentées d'une manière complètement non-standard, de sorte que les résultats peuvent être différents et devraient provenir de quelque chose comme grep ou perl.

Regex Line Position ancres ^ et $
^ correspond au début du flux d'entrée ainsi qu'à toute position immédiatement après un <LF>. Comme FINDSTR interrompt également les lignes après <LF>, une simple regex de "^" correspondra toujours à toutes les lignes d'un fichier, même un fichier binaire.

$ correspond à n'importe quelle position précédant immédiatement un <CR>. Cela signifie qu'une chaîne de recherche regex contenant $ ne correspondra jamais à aucune ligne dans un fichier texte de style Unix, et ne correspondra pas non plus à la dernière ligne d'un fichier texte Windows s'il manque le marqueur EOL de <CR> <LF>.

Remarque - Comme indiqué précédemment, les entrées redirigées et redirigées vers FINDSTR peuvent contenir <CR><LF> qui n'est pas dans la source. Évidemment, cela peut avoir un impact sur une recherche regex qui utilise $ .

Toute chaîne de recherche avec des caractères avant ^ ou après $ ne trouvera jamais de correspondance.

Options de position / B / E / X
Les options positionnelles fonctionnent de la même manière que ^ et $ , sauf qu'elles fonctionnent également pour les chaînes de recherche littérales.

/ B fonctionne comme ^ au début d'une chaîne de recherche regex.

/ E fonctionne comme $ à la fin d'une chaîne de recherche regex.

/ X fonctionne de la même façon que ^ au début et $ à la fin d'une chaîne de recherche regex.

Limite du mot Regex
\< doit être le premier terme de l'expression rationnelle. L'expression rationnelle ne correspondra à rien si d'autres caractères la précèdent. \< correspond soit au tout début de l'entrée, soit au début d'une ligne (la position immédiatement après un <LF>), soit à la position qui suit immédiatement tout caractère "non-mot". Le caractère suivant n'a pas besoin d'être un caractère "mot".

\> doit être le dernier terme de la regex. L'expression rationnelle ne correspondra à rien si d'autres caractères la suivent. \> correspond soit à la fin de l'entrée, la position immédiatement avant un <CR>, soit à la position précédant immédiatement tout caractère "non-mot". Le caractère précédent n'a pas besoin d'être un caractère "mot".

Voici une liste complète des caractères "non-word", représentés par le code octet décimal. Note - cette liste a été compilée sur une machine américaine. Je ne sais pas quel impact d'autres langues peuvent avoir sur cette liste.

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

Classes de classes de caractères Regex [xy]
Les plages de classes de caractères ne fonctionnent pas comme prévu. Voir cette question: Pourquoi findstr ne gère-t-il pas correctement le cas (dans certaines circonstances)? , avec cette réponse: https://.com/a/8767815/1012053 .

Le problème est FINDSTR ne rassemble pas les caractères par leur valeur de code d'octet (communément considéré comme le code ASCII, mais ASCII est seulement défini de 0x00 - 0x7F). La plupart des implémentations de regex traiteraient [AZ] comme toutes les lettres majuscules anglaises majuscules. Mais FINDSTR utilise une séquence de classement qui correspond approximativement au fonctionnement de SORT. Donc [AZ] comprend l'alphabet anglais complet, en majuscules et minuscules (sauf pour "a"), ainsi que des caractères alpha non-anglais avec des signes diacritiques.

Voici une liste complète de tous les caractères supportés par FINDSTR, triés dans la séquence de classement utilisée par FINDSTR pour établir des plages de classes de caractères regex. Les caractères sont représentés comme leur valeur de code octet décimal. Je crois que la séquence de classement a le plus de sens si les caractères sont visualisés en utilisant la page de code 437. Note - cette liste a été compilée sur une machine américaine. Je ne sais pas quel impact d'autres langues peuvent avoir sur cette liste.

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

Limite de limite de classe de caractères Regex et BUG
FINDSTR n'est pas limité à un maximum de 15 termes de classe de caractères dans une regex, il ne gère pas correctement une tentative de dépassement de la limite. L'utilisation de 16 termes de classe de caractères ou plus entraîne l' affichage d' un pop-up Windows interactif indiquant que l' utilitaire "Find String (QGREP) a rencontré un problème et doit être fermé." Nous sommes désolés pour ce désagrément. " Le texte du message varie légèrement en fonction de la version de Windows. Voici un exemple d'un FINDSTR qui échouera:

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]

This bug was reported by DosTips user Judago here . It has been confirmed on XP, Vista, and Windows 7.

Regex searches fail (and may hang indefinitely) if they include byte code 0xFF (decimal 255)
Any regex search that includes byte code 0xFF (decimal 255) will fail. It fails if byte code 0xFF is included directly, or if it is implicitly included within a character class range. Remember that FINDSTR character class ranges do not collate characters based on the byte code value. Character <0xFF> appears relatively early in the collation sequence between the <space> and <tab> characters. So any character class range that includes both <space> and <tab> will fail.

The exact behavior changes slightly depending on the Windows version. Windows 7 hangs indefinitely if 0xFF is included. XP doesn't hang, but it always fails to find a match, and occasionally prints the following error message - "The process tried to write to a nonexistent pipe."

I no longer have access to a Vista machine, so I haven't been able to test on Vista.

Regex bug: . and [^anySet] can match End-Of-File
The regex . meta-character should only match any character other than <CR> or <LF> . There is a bug that allows it to match the End-Of-File if the last line in the file is not terminated by <CR> or <LF> . However, the . will not match an empty file.

For example, a file named "test.txt" containing a single line of x , without terminating <CR> or <LF> , will match the following:

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

This bug has been confirmed on XP and Win7.

The same seems to be true for negative character sets. Something like [^abc] will match End-Of-File. Positive character sets like [abc] seem to work fine. I have only tested this on Win7.


Answer #5

Préface
Une grande partie de l'information contenue dans cette réponse a été recueillie en fonction des expériences effectuées sur une machine Vista. Sauf indication contraire explicite, je n'ai pas confirmé si l'information s'applique à d'autres versions de Windows.

Sortie FINDSTR
La documentation ne dérange jamais pour expliquer la sortie de FINDSTR. Cela fait allusion au fait que les lignes correspondantes sont imprimées, mais rien de plus.

Le format de la sortie de ligne correspondante est le suivant:

filename: lineNumber: lineOffset: texte

fileName: = Le nom du fichier contenant la ligne correspondante. Le nom de fichier n'est pas imprimé si la demande était explicitement pour un seul fichier, ou si vous recherchez une entrée canalisée ou une entrée redirigée. Une fois imprimé, le nom de fichier inclura toujours toutes les informations de chemin fournies. Des informations supplémentaires sur le chemin seront ajoutées si l'option /S est utilisée. Le chemin imprimé est toujours relatif au chemin fourni, ou relatif au répertoire courant s'il n'y en a pas.

Remarque - Le préfixe du nom de fichier peut être évité lors de la recherche de plusieurs fichiers en utilisant les caractères génériques non standard (et mal documentés) < et > . Les règles exactes du fonctionnement de ces caractères génériques peuvent être trouvées here . Enfin, vous pouvez regarder cet exemple de la façon dont les caractères génériques non standard fonctionnent avec FINDSTR .

lineNumber: = Le numéro de ligne de la ligne correspondante représentée comme une valeur décimale avec 1 représentant la 1ère ligne de l'entrée. Seule l'option if /N imprimée est spécifiée.

lineOffset: = Décalage octet décimal du début de la ligne correspondante, avec 0 représentant le 1er caractère de la 1ère ligne. Seule l'option d' /O imprimée est spécifiée. Ce n'est pas le décalage du match dans la ligne. C'est le nombre d'octets depuis le début du fichier jusqu'au début de la ligne.

text = La représentation binaire de la ligne correspondante, y compris tout <CR> et / ou <LF>. Rien n'est exclu de la sortie binaire, de sorte que cet exemple qui correspond à toutes les lignes produira une copie binaire exacte du fichier d'origine.

FINDSTR "^" FILE >FILE_COPY

La plupart des caractères de contrôle et de nombreux caractères ASCII étendus s'affichent sous forme de points sur XP
FINDSTR sur XP affiche la plupart des caractères de contrôle non imprimables à partir des lignes correspondantes sous forme de points (points) sur l'écran. Les caractères de contrôle suivants sont des exceptions; ils s'affichent comme eux-mêmes: onglet 0x09, LineAge 0x0A, onglet vertical 0x0B, flux de formulaire 0x0C, retour chariot 0x0D.

XP FINDSTR convertit également un certain nombre de caractères ASCII étendus en points. Les caractères ASCII étendus qui s'affichent sous la forme de points sur XP sont les mêmes que ceux qui sont transformés lorsqu'ils sont fournis sur la ligne de commande. Voir la section "Limites de caractères pour les paramètres de ligne de commande - Transformation ASCII étendue" , plus loin dans ce post

Les caractères de contrôle et ASCII étendu ne sont pas convertis en points sur XP si la sortie est redirigée vers un fichier, ou dans une clause FOR IN ().

Vista et Windows 7 affichent toujours tous les caractères comme eux-mêmes, jamais comme des points.

Codes retour (ERRORLEVEL)

  • 0 (succès)
    • La correspondance a été trouvée dans au moins une ligne d'au moins un fichier.
  • 1 (échec)
    • Aucune correspondance n'a été trouvée dans une ligne de n'importe quel fichier.
    • Couleur non valide spécifiée par l'option /A:xx
  • 2 (erreur)
    • Options incompatibles /L et /R spécifiés
    • Argument manquant après /A: /F: /C: /D: ou /G:
    • Fichier spécifié par /F:file ou /G:file introuvable
  • 255 (erreur)
    • Trop de termes de classe de caractères d'expression régulière
      voir limite de limite de classe de caractères Regex et BUG dans la partie 2 de la réponse

Source de données à rechercher (mise à jour basée sur des tests avec Windows 7)
Findstr peut rechercher des données à partir d'une seule des sources suivantes:

  • noms de fichiers spécifiés en tant qu'arguments et / ou en utilisant l'option /F:file .

  • stdin via redirection findstr "searchString" <file

  • flux de données d'un type file | findstr "searchString" pipe type file | findstr "searchString" type file | findstr "searchString"

Les arguments / options ont préséance sur la redirection, qui a la priorité sur les données canalisées.

Les arguments de nom de fichier et /F:file peuvent être combinés. Des arguments de nom de fichier multiples peuvent être utilisés. Si plusieurs options de /F:file sont spécifiées, seul le dernier est utilisé. Les caractères génériques sont autorisés dans les noms de fichier, mais pas dans le fichier pointé par /F:file .

Source des chaînes de recherche (Mise à jour basée sur des tests avec Windows 7)
Les options /G:file et /C:string peuvent être combinées. Plusieurs options de /C:string peuvent être spécifiées. Si plusieurs options de /G:file sont spécifiées, seul le dernier est utilisé. Si soit /G:file ou /C:string est utilisé, alors tous les arguments non-option sont supposés être des fichiers à rechercher. Si ni /G:file ni /C:string n'est utilisé, le premier argument non-option est traité comme une liste de termes de recherche délimités par des espaces.

Les noms de fichiers ne doivent pas être cités dans le fichier lors de l'utilisation de l'option /F:FILE .
Les noms de fichiers peuvent contenir des espaces et d'autres caractères spéciaux. La plupart des commandes exigent que ces noms de fichiers soient cités. Mais l'option FINDSTR /F:files.txt requiert que les noms de fichier dans files.txt ne soient PAS entre guillemets. Le fichier ne sera pas trouvé si le nom est cité.

BOGUE - Les noms de fichiers courts 8.3 peuvent rompre les options /D et /S
Comme pour toutes les commandes Windows, FINDSTR tentera de faire correspondre le nom long et le nom court 8.3 lors de la recherche de fichiers à rechercher. Supposons que le dossier actuel contient les fichiers non vides suivants:

b1.txt
b.txt2
c.txt

La commande suivante trouvera avec succès tous les 3 fichiers:

findstr /m "^" *.txt

b.txt2 correspond car le nom court correspondant B9F64~1.TXT correspond. Ceci est cohérent avec le comportement de toutes les autres commandes Windows.

Mais un bogue avec les options /D et /S fait que les commandes suivantes ne trouvent que b1.txt

findstr /m /d:. "^" *.txt
findstr /m /s "^" *.txt

Le bogue empêche la b.txt2 de b.txt2 , ainsi que tous les noms de fichiers qui sont b.txt2 après b.txt2 dans le même répertoire. Des fichiers supplémentaires qui trient auparavant, comme a.txt , sont trouvés. Les fichiers supplémentaires qui sont d.txt plus tard, comme d.txt , sont manqués une fois que le bogue a été déclenché.

Chaque répertoire recherché est traité indépendamment. Par exemple, l'option /S commencerait à chercher dans un dossier enfant après avoir échoué à trouver les fichiers dans le parent, mais une fois que le bogue aura manqué un nom de fichier court dans l'enfant, tous les fichiers suivants de ce dossier enfant manquer.

Les commandes fonctionnent sans bug si les mêmes noms de fichiers sont créés sur une machine dont la génération de noms NTFS 8.3 est désactivée. Bien sûr, b.txt2 ne serait pas trouvé, mais c.txt serait trouvé correctement.

Tous les noms courts ne déclenchent pas le bug. Toutes les instances de comportement buggé que j'ai vu impliquent une extension qui est plus longue que 3 caractères avec un nom court de 8.3 qui commence le même comme un nom normal qui n'exige pas un nom 8.3.

Le bug a été confirmé sur XP, Vista et Windows 7.

Caractères non imprimables et l'option /P
L'option /P force FINDSTR à ignorer tout fichier contenant l'un des codes d'octets décimaux suivants:
0-7, 14-25, 27-31.

En d'autres termes, l'option /P ignore uniquement les fichiers contenant des caractères de contrôle non imprimables. Les caractères de contrôle sont des codes inférieurs ou égaux à 31 (0x1F). FINDSTR traite les caractères de contrôle suivants comme imprimables:

 8  0x08  backspace
 9  0x09  horizontal tab
10  0x0A  line feed
11  0x0B  vertical tab
12  0x0C  form feed
13  0x0D  carriage return
26  0x1A  substitute (end of text)

Tous les autres caractères de contrôle sont traités comme non-imprimables, la présence de laquelle provoque l'option /P pour ignorer le fichier.

L'entrée Piped and Redirected peut avoir <CR><LF> ajouté
Si l'entrée est canalisée et que le dernier caractère du flux n'est pas <LF> , alors FINDSTR ajoute automatiquement <CR><LF> à l'entrée. Cela a été confirmé sur XP, Vista et Windows 7. (Je pensais que le tuyau de Windows était responsable de la modification de l'entrée, mais j'ai découvert depuis que FINDSTR est en train de faire la modification.)

La même chose est vraie pour l'entrée redirigée sur Vista. Si le dernier caractère d'un fichier utilisé comme entrée redirigée n'est pas <LF> , alors FINDSTR ajoutera automatiquement <CR><LF> à l'entrée. Cependant, XP et Windows 7 n'altèrent pas les entrées redirigées.

FINDSTR se bloque sur XP et Windows 7 si l'entrée redirigée ne se termine pas avec <LF>
C'est une "caractéristique" désagréable sur XP et Windows 7. Si le dernier caractère d'un fichier utilisé comme entrée redirigée ne se termine pas par <LF> , alors FINDSTR se bloquera indéfiniment une fois qu'il aura atteint la fin du fichier redirigé.

La dernière ligne de données Piped peut être ignorée si elle est composée d'un seul caractère
Si l'entrée est connectée et que la dernière ligne est constituée d'un seul caractère qui n'est pas suivi de <LF> , alors FINDSTR ignore complètement la dernière ligne.

Exemple - La première commande avec un seul caractère et pas <LF> ne correspond pas, mais la deuxième commande avec 2 caractères fonctionne bien, tout comme la troisième commande qui a un caractère avec un retour à la ligne de fin.

> set /p "=x" <nul | findstr "^"

> set /p "=xx" <nul | findstr "^"
xx

> echo x| findstr "^"
x

Rapporté par l'utilisateur de DosTips Sponge Belly au nouveau bug findstr . Confirmé sur XP, Windows 7 et Windows 8. N'a pas encore entendu parler de Vista. (Je n'ai plus Vista à tester).

Syntaxe d'option
Les options peuvent être préfixées avec / ou - options peuvent être concaténées après un seul / ou - . Cependant, la liste d'options concaténées peut contenir au plus une option multicharacter telle que OFF ou F :, et l'option multi-caractères doit être la dernière option de la liste.

Voici des façons équivalentes d'exprimer une recherche regex insensible à la casse pour toute ligne contenant à la fois "bonjour" et "au revoir" dans n'importe quel ordre

  • /i /r /c:"hello.*goodbye" /c:"goodbye.*hello"

  • -i -r -c:"hello.*goodbye" /c:"goodbye.*hello"

  • /irc:"hello.*goodbye" /c:"goodbye.*hello"

Rechercher les limites de longueur de chaîne
Sur Vista, la longueur maximale autorisée pour une seule chaîne de recherche est de 511 octets. Si une chaîne de recherche dépasse 511, le résultat est une FINDSTR: Search string too long. erreur avec ERRORLEVEL 2.

Lorsque vous effectuez une recherche d'expression régulière, la longueur maximale de la chaîne de recherche est 254. Une expression régulière d'une longueur comprise entre 255 et 511 entraîne une FINDSTR: Out of memory avec ERRORLEVEL 2. Une longueur d'expression régulière> 511 aboutit à FINDSTR: Search string too long. Erreur.

Sous Windows XP, la longueur de la chaîne de recherche est apparemment plus courte. Erreur Findstr: "Chaîne de recherche trop longue": Comment extraire et faire correspondre la sous-chaîne dans la boucle "for"? La limite XP est de 127 octets pour les recherches littérales et regex.

Limites de longueur de ligne
Les fichiers spécifiés en tant qu'argument de ligne de commande ou via l'option / F: FILE n'ont pas de limite de longueur de ligne connue. Les recherches ont été exécutées avec succès sur un fichier de 128 Mo qui ne contenait pas un seul <LF>.

Les données canalisées et les entrées redirigées sont limitées à 8191 octets par ligne. Cette limite est une "caractéristique" de FINDSTR. Ce n'est pas inhérent aux tuyaux ou à la redirection. FINDSTR utilisant une entrée redirigée stdin ou piped ne correspondra jamais à une ligne de plus de 8k octets. Les lignes> = 8k génèrent un message d'erreur à stderr, mais ERRORLEVEL reste à 0 si la chaîne de recherche est trouvée dans au moins une ligne d'au moins un fichier.

Type de recherche par défaut: Littéral vs Expression Régulière
/C:"string" - La valeur par défaut est / L littéral. Combiner explicitement l'option / L avec / C: "string" fonctionne certainement mais est redondant.

"string argument" - La valeur par défaut dépend du contenu de la toute première chaîne de recherche. (N'oubliez pas que <espace> est utilisé pour délimiter les chaînes de recherche.) Si la première chaîne de recherche est une expression régulière valide contenant au moins un méta-caractère non échappé, toutes les chaînes de recherche sont traitées comme des expressions régulières. Sinon, toutes les chaînes de recherche sont traitées comme des littéraux. Par exemple, "51.4 200" sera traité comme deux expressions régulières car la première chaîne contient un point non échappé, alors que "200 51.4" sera traité comme deux littéraux car la première chaîne ne contient aucun méta-caractère.

/G:file - La valeur par défaut dépend du contenu de la première ligne non vide du fichier. Si la première chaîne de recherche est une expression régulière valide contenant au moins un méta-caractère non échappé, toutes les chaînes de recherche sont traitées comme des expressions régulières. Sinon, toutes les chaînes de recherche sont traitées comme des littéraux.

Recommandation - Toujours spécifier explicitement /L option littérale ou /R expression régulière option lors de l'utilisation de "string argument" ou /G:file .

BOGUE - La spécification de plusieurs chaînes de recherche littérales peut donner des résultats non fiables

L'exemple FINDSTR simple suivant ne parvient pas à trouver une correspondance, même si cela doit être le cas.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Ce bogue a été confirmé sur Windows Server 2003, Windows XP, Vista et Windows 7.

Basé sur des expériences, FINDSTR peut échouer si toutes les conditions suivantes sont remplies:

  • La recherche utilise plusieurs chaînes de recherche littérales
  • Les chaînes de recherche ont des longueurs différentes
  • Une chaîne de recherche courte comporte un certain chevauchement avec une chaîne de recherche plus longue
  • La recherche est sensible à la casse (option non /I )

Dans chaque échec que j'ai vu, c'est toujours l'une des chaînes de recherche les plus courtes qui échoue.

Pour plus d'informations, consultez Pourquoi cet exemple FINDSTR avec plusieurs chaînes de recherche littérales ne correspond-il pas?

Citations et backslahses dans les arguments de la ligne de commande - Note:
Les informations contenues dans cette section en surbrillance ne sont pas exactes à 100%. Après avoir écrit cette section, l'utilisateur MC ND m'a indiqué une référence qui documente comment la bibliothèque Microsoft C / C ++ analyse les paramètres . Il est horriblement compliqué, mais il semble prédire avec précision les règles de barre oblique inverse et de citation pour les arguments de la ligne de commande FINDSTR. Je vous recommande d'utiliser les informations en surbrillance ci-dessous comme guide, mais si vous voulez des informations plus précises, reportez-vous au lien.

Escaping Quote dans les chaînes de recherche en ligne de commande
Les citations dans les chaînes de recherche en ligne de commande doivent être échappées avec une barre oblique inversée comme \" .Cela est vrai pour les chaînes de recherche littérales et regex.Cette information a été confirmée sur XP, Vista et Windows 7.

Remarque: La citation peut également avoir besoin d'être échappée pour l'analyseur CMD.EXE, mais cela n'a rien à voir avec FINDSTR. Par exemple, pour rechercher une seule citation, vous pouvez utiliser:

FINDSTR \^" file && echo found || echo not found

Échap de barre oblique inverse dans les chaînes de recherche littérales de ligne de commande
La barre oblique inverse dans une chaîne de recherche littérale peut normalement être représentée par \ ou \\ . Ils sont typiquement équivalents. (Il peut y avoir des cas inhabituels dans Vista où le backslash doit toujours être échappé, mais je n'ai plus de machine Vista à tester) .

Mais il y a des cas particuliers:

Lorsque vous recherchez des antislashs consécutifs, tous sauf le dernier doivent être échappés. La dernière barre oblique inverse peut éventuellement être échappée.

  • \\ peut être codé comme \\\ ou \\\\
  • \\\ peut être codé comme \\\\\\ ou \\\\\\

La recherche d'une ou de plusieurs barres obliques inverses avant une citation est bizarre. La logique suggère que la citation doit être échappée, et que chaque antislash principal devrait être échappé, mais cela ne fonctionne pas! Au lieu de cela, chaque antislash principal doit être à double échappement, et la citation est normalement échappée:

  • \" doit être codé comme \\\\\"
  • \\" doit être codé comme \\\\\\\\\"

Comme indiqué précédemment, une ou plusieurs guillemets échappés peuvent également nécessiter l'échappement avec ^ pour l'analyseur CMD

L'information dans cette section a été confirmée sur XP et Windows 7.

Échapper à la barre oblique inverse dans les chaînes de recherche regex en ligne de commande

  • Vista uniquement: une \\\\ dans une regex doit être soit double, soit comme \\\\ , soit seule dans une classe de caractères comme [\\]

  • XP et Windows 7: Une barre oblique inverse dans une regex peut toujours être représentée par [\\] . Il peut normalement être représenté comme \\ . Mais cela ne fonctionne jamais si l'antislash précède une citation échappée.

    Une ou plusieurs barres obliques inverses avant une citation échappée doivent être soit double, soit codées comme [\\]

    • \" peut être codé comme \\\\\" ou [\\]\"
    • \\" peut être codé sous la forme \\\\\\\\\"

Escaping Quote et Backslash dans / G: FICHIER chaînes de recherche littérales
Les guillemets autonomes et les antislashs dans un fichier littéral de chaîne de recherche spécifié par / G: n'ont pas besoin d'être échappés, mais ils peuvent l'être.

" et \" sont équivalents.

\ et \\ sont équivalents.

Si l'intention est de trouver \\, au moins la barre oblique inverse doit être échappée. Les deux \\\ et \\\\ fonctionnent.

Si l'intention est de trouver \ ", au moins la barre oblique inverse doit être échappée. \\" et \\\" fonctionnent.

Escaping Quote et Backslash dans / G: FICHIER des chaînes de recherche regex
C'est le seul cas où les séquences d'échappement fonctionnent comme prévu en fonction de la documentation. La citation n'est pas un métacaractère regex, elle n'a donc pas besoin d'être échappée (mais peut l'être). Backslash est un méta-caractère regex, il doit donc être échappé.

Limites de caractères pour les paramètres de ligne de commande - Transformation ASCII étendue
Le caractère null (0x00) ne peut pas apparaître dans aucune chaîne sur la ligne de commande. Tout autre caractère d'octet unique peut apparaître dans la chaîne (0x01 - 0xFF). Toutefois, FINDSTR convertit de nombreux caractères ASCII étendus trouvés dans les paramètres de ligne de commande en d'autres caractères. Cela a un impact majeur de deux manières:

1) De nombreux caractères ASCII étendus ne correspondent pas s'ils sont utilisés comme chaîne de recherche sur la ligne de commande. Cette limitation est la même pour les recherches littérales et regex. Si une chaîne de recherche doit contenir ASCII étendu, l'option /G:FILE doit être utilisée à la place.

2) FINDSTR peut ne pas trouver un fichier si le nom contient des caractères ASCII étendus et si le nom du fichier est spécifié sur la ligne de commande. Si un fichier à rechercher contient des caractères ASCII étendus dans le nom, l'option /F:FILE doit être utilisée à la place.

Voici une liste complète des transformations de caractères ASCII étendues que FINDSTR effectue sur les chaînes de ligne de commande. Chaque caractère est représenté par la valeur du code octet décimal. Le premier code représente le caractère fourni sur la ligne de commande et le deuxième code représente le caractère dans lequel il est transformé. Note - cette liste a été compilée sur une machine américaine. Je ne sais pas quel impact d'autres langues peuvent avoir sur cette liste.

158 treated as 080     199 treated as 221     226 treated as 071
169 treated as 170     200 treated as 043     227 treated as 112
176 treated as 221     201 treated as 043     228 treated as 083
177 treated as 221     202 treated as 045     229 treated as 115
178 treated as 221     203 treated as 045     231 treated as 116
179 treated as 221     204 treated as 221     232 treated as 070
180 treated as 221     205 treated as 045     233 treated as 084
181 treated as 221     206 treated as 043     234 treated as 079
182 treated as 221     207 treated as 045     235 treated as 100
183 treated as 043     208 treated as 045     236 treated as 056
184 treated as 043     209 treated as 045     237 treated as 102
185 treated as 221     210 treated as 045     238 treated as 101
186 treated as 221     211 treated as 043     239 treated as 110
187 treated as 043     212 treated as 043     240 treated as 061
188 treated as 043     213 treated as 043     242 treated as 061
189 treated as 043     214 treated as 043     243 treated as 061
190 treated as 043     215 treated as 043     244 treated as 040
191 treated as 043     216 treated as 043     245 treated as 041
192 treated as 043     217 treated as 043     247 treated as 126
193 treated as 045     218 treated as 043     249 treated as 250
194 treated as 045     219 treated as 221     251 treated as 118
195 treated as 043     220 treated as 095     252 treated as 110
196 treated as 045     222 treated as 221     254 treated as 221
197 treated as 043     223 treated as 095
198 treated as 221     224 treated as 097

Tout caractère> 0 ne figurant pas dans la liste ci-dessus est traité comme lui-même, y compris <CR> et < LF> . Le moyen le plus simple d'inclure des caractères impairs comme <CR> et <LF> est de les placer dans une variable d'environnement et d'utiliser l'expansion retardée dans l'argument de la ligne de commande.

Limites de caractères pour les chaînes trouvées dans les fichiers spécifiés par / G: FILE et / F: options FILE
Le caractère nul (0x00) peut apparaître dans le fichier, mais il fonctionne comme le terminateur de chaîne C. Tous les caractères après un caractère nul sont traités comme une chaîne différente comme s'ils se trouvaient sur une autre ligne.

Les caractères <CR> et <LF> sont traités comme des terminaisons de ligne qui terminent une chaîne et ne sont pas inclus dans la chaîne.

Tous les autres caractères à un seul octet sont parfaitement inclus dans une chaîne.

Recherche de fichiers Unicode
FINDSTR ne peut pas rechercher correctement la plupart des Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) car il ne peut pas rechercher des octets nulles et Unicode contient généralement de nombreux octets nuls.

Toutefois, la commande TYPE convertit UTF-16LE avec BOM en un jeu de caractères à un seul octet, de sorte qu'une commande comme celle-ci fonctionnera avec UTF-16LE avec BOM.

type unicode.txt|findstr "search"

Notez que les points de code Unicode qui ne sont pas pris en charge par votre page de codes active seront convertis en ? personnages.

Il est possible de rechercher UTF-8 tant que votre chaîne de recherche contient uniquement ASCII. Toutefois, la sortie de la console de tous les caractères UTF-8 multi-octets ne sera pas correcte. Mais si vous redirigez la sortie vers un fichier, le résultat sera encodé correctement en UTF-8. Notez que si le fichier UTF-8 contient une nomenclature, la nomenclature sera considérée comme faisant partie de la première ligne, ce qui pourrait annuler une recherche qui correspond au début d'une ligne.

Il est possible de rechercher des caractères UTF-8 multi-octets si vous placez votre chaîne de recherche dans un fichier de recherche codé UTF-8 (sans nomenclature) et utilisez l'option / G.

Fin de ligne
FINDSTR interrompt les lignes immédiatement après chaque <LF>. La présence ou l'absence de <CR> n'a aucun impact sur les sauts de ligne.

Recherche sur les sauts de ligne
Comme prévu, le . Le métacaractère regex ne correspondra pas à <CR> ou <LF>. Mais il est possible d'effectuer une recherche sur un saut de ligne à l'aide d'une chaîne de recherche en ligne de commande. Les caractères <CR> et <LF> doivent tous deux correspondre explicitement. Si une correspondance à plusieurs lignes est trouvée, seule la première ligne du match est imprimée. FINDSTR revient ensuite à la deuxième ligne de la source et recommence la recherche - une sorte de fonction de type "regarder en avant".

Supposons que TEXT.TXT a ces contenus (pourrait être un style Unix ou Windows)

A
A
A
B
A
A

Alors ce script

@echo off
setlocal
::Define LF variable containing a linefeed (0x0A)
set LF=^


::Above 2 blank lines are critical - do not remove

::Define CR variable containing a carriage return (0x0D)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

setlocal enableDelayedExpansion
::regex "!CR!*!LF!" will match both Unix and Windows style End-Of-Line
findstr /n /r /c:"A!CR!*!LF!A" TEST.TXT

donne ces résultats

1:A
2:A
5:A

La recherche sur les sauts de ligne à l'aide de l'option / G: FILE est imprécise car la seule façon de faire correspondre <CR> ou <LF> est via une expression de plage de classes de caractères regex qui prend en sandwich les caractères EOL.

  • [<TAB>-<0x0B>] correspond à <LF>, mais il correspond également à <TAB> et <0x0B>

  • [<0x0C>-!] <CR>, mais il correspond aussi à <0x0C> et!

    Remarque - les images ci-dessus sont des représentations symboliques du flux d'octets regex car je ne peux pas représenter graphiquement les caractères.

La réponse a continué dans la partie 2 ci-dessous ...





findstr