web-dev-qa-db-fra.com

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

La commande Windows FINDSTR est horriblement documentée. Il existe une aide de base en ligne de commande disponible via FINDSTR /? ou HELP FINDSTR, mais elle est terriblement inadéquate. Il existe encore un peu plus de documentation en ligne sur https://docs.Microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

De nombreuses fonctionnalités et limitations de FINDSTR ne sont même pas mentionnées dans la documentation. Ils ne pourraient pas non plus être anticipés sans connaissance préalable et/ou sans expérimentation minutieuse.

La question est donc la suivante: Quelles sont les fonctionnalités non documentées de FINDSTR et leurs limitations?

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

A) Les développeurs peuvent tirer pleinement parti des fonctionnalités disponibles.

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

Assurez-vous de connaître la documentation existante avant de répondre. Si les informations sont couvertes par l’aide, alors elles n’ont pas leur place ici.

Ce n’est pas non plus un endroit où montrer des utilisations intéressantes de FINDSTR. Si une personne logique peut anticiper le comportement d’une utilisation particulière de FINDSTR sur la base de la documentation, elle n’a pas sa place ici.

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

182
dbenham

Préface
La plupart des informations contenues dans cette réponse ont été recueillies à partir d'expériences réalisées sur une machine Vista. Sauf indication contraire explicite, je n'ai pas confirmé si les informations s'appliquaient aux autres versions de Windows.

sortie FINDSTR
La documentation ne se soucie jamais d’expliquer le résultat 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:

nomfichier: numéroLigne: numéroLigne: texte

nomFichier: = Nom du fichier contenant la ligne correspondante. Le nom de fichier n'est pas imprimé si la demande concerne explicitement un seul fichier, ou si vous recherchez une entrée redirigée ou redirigée. Une fois imprimé, le nom de fichier inclut toujours les informations de chemin fournies. Des informations de chemin supplémentaires seront ajoutées si l'option /S est utilisée. Le chemin imprimé est toujours relatif au chemin fourni, ou au répertoire en cours si aucun n’est fourni.

Remarque - Le préfixe du nom de fichier peut être évité lors de la recherche de plusieurs fichiers en utilisant les caractères joker caractères génériques non standard (et mal documentés)< et >. Les règles exactes sur le fonctionnement de ces caractères génériques peuvent être trouvées ici . Enfin, vous pouvez regarder ceci 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 sous forme de valeur décimale, 1 représentant la 1ère ligne de l'entrée. Ne s'imprime que si l'option /N est spécifiée.

lineOffset: = décalage de l'octet décimal du début de la ligne correspondante, 0 représentant le 1er caractère de la 1re ligne. Ne s'imprime que si l'option /O est spécifiée. C'est pas le décalage de la correspondance dans la ligne. C'est le nombre d'octets du début du fichier 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 laissé en dehors 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 étendus ASCII sont affichés sous forme de points sous XP
FINDSTR sur XP affiche la plupart des caractères de contrôle non imprimables des lignes correspondantes sous forme de points (points) à l'écran. Les caractères de contrôle suivants sont des exceptions; ils s'affichent sous la forme eux-mêmes: onglet 0x09, saut de ligne 0x0A, onglet vertical 0x0B, saut de page 0x0C, retour chariot 0x0D.

XP FINDSTR convertit également un certain nombre de caractères étendus ASCII en points. Les caractères étendus ASCII qui s'affichent sous forme de points sur XP sont identiques à 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 étendue ASCII" ", plus loin dans cet article.

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

Vista et Windows 7 affichent toujours tous les caractères comme tels, jamais comme des points.

Codes de retour (ERRORLEVEL)

  • 0 (success)
    • La correspondance a été trouvée dans au moins une ligne d'au moins un fichier.
  • 1 (failure)
    • Aucune correspondance n'a été trouvée dans aucune ligne d'un fichier.
    • Couleur non valide spécifiée par l'option /A:xx
  • 2 (error)
    • Options incompatibles /L et /R spécifiées toutes les deux
    • Argument manquant après /A:, /F:, /C:, /D: ou /G:
    • Fichier spécifié par /F:file ou /G:file introuvable
  • 255 (erreur)

Source des données à rechercher (mis à jour à partir de tests avec Windows 7)
Findstr peut rechercher des données dans l'une des sources suivantes:

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

  • stdin via la redirection findstr "searchString" <file

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

Les arguments/options ont priorité 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. Plusieurs arguments de nom de fichier peuvent être utilisés. Si plusieurs options /F:file sont spécifiées, seule la dernière est utilisée. Les caractères génériques sont autorisés dans les arguments de nom de fichier, mais pas dans le fichier pointé par /F:file.

Source des chaînes de recherche (mis à jour à partir de tests avec Windows 7)
Les options /G:file et /C:string peuvent être combinées. Plusieurs options /C:string peuvent être spécifiées. Si plusieurs options /G:file sont spécifiées, seule la dernière est utilisée. Si /G:file ou /C:string est utilisé, tous les arguments sans option sont considérés comme des fichiers à rechercher. Si ni /G:file ni /C:string ne sont utilisés, le premier argument sans option est traité comme une liste de termes de recherche délimités par des espaces.

Les noms de fichier ne doivent pas être cités dans le fichier lorsque l'option /F:FILE est utilisée.
Les noms de fichier peuvent contenir des espaces et d’autres caractères spéciaux. La plupart des commandes nécessitent que ces noms de fichiers soient cités. Mais l'option FINDSTR /F:files.txt nécessite que les noms de fichiers contenus dans le fichier files.txt NE soient PAS cités. Le fichier ne sera pas trouvé si le nom est cité.

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

b1.txt
b.txt2
c.txt

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

findstr /m "^" *.txt

b.txt2 correspond car le nom abrégé 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 recherche de b.txt2, ainsi que tous les noms de fichiers qui se trient après b.txt2 dans le même répertoire. Des fichiers supplémentaires triés auparavant, tels que a.txt, ont été trouvés. Les fichiers supplémentaires triés ultérieurement, tels que d.txt, ne sont pas pris en compte une fois le bogue déclenché.

Chaque répertoire recherché est traité indépendamment. Par exemple, l'option /S peut commencer à rechercher dans un dossier enfant après avoir échoué dans la recherche de fichiers dans le parent, mais une fois que le bogue provoque l'absence d'un nom de fichier court dans l'enfant, puis de tous les fichiers suivants dans cet enfant. dossier serait également manquer.

Les commandes fonctionnent sans bug si les mêmes noms de fichiers sont créés sur un ordinateur sur lequel 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 abrégés ne déclenchent pas le bogue. Toutes les occurrences de comportement erroné que j'ai rencontrées impliquent une extension de plus de 3 caractères avec un nom 8.3 court commençant le même qu'un nom normal ne nécessitant pas de nom 8.3.

Le bogue 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 considérés comme non imprimables. En raison de leur présence, l'option /P ignore le fichier.

L'entrée canalisée et redirigée peut avoir <CR><LF> ajouté
Si l'entrée est transférée et que le dernier caractère du flux n'est pas <LF>, FINDSTR ajoutera automatiquement <CR><LF> à l'entrée. Cela a été confirmé sur XP, Vista et Windows 7. (J'avais l'habitude de penser que le tube Windows était responsable de la modification de l'entrée, mais j'ai depuis découvert que FINDSTR était en train de le modifier.)

Il en va de même pour les entrées redirigées sous Vista. Si le dernier caractère d'un fichier utilisé comme entrée redirigée n'est pas <LF>, FINDSTR ajoutera automatiquement <CR><LF> à l'entrée. Cependant, XP et Windows 7 ne modifient pas les entrées redirigées.

FINDSTR se bloque sur XP et Windows 7 si l'entrée redirigée ne se termine pas par <LF>
Il s’agit d’une "fonctionnalité" 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>, FINDSTR se bloque indéfiniment une fois atteint la fin du fichier redirigé.

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

Exemple - La première commande avec un seul caractère sans no <LF> ne correspond pas, mais la deuxième commande avec 2 caractères fonctionne correctement, de même que la troisième commande qui comporte un caractère avec une nouvelle ligne.

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

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

> echo x| findstr "^"
x

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

Option syntaxe
Les options peuvent être précédées de / ou - Les options peuvent être concaténées après un seul / ou -. Toutefois, la liste des options concaténées peut contenir au plus une option multicaractère telle que OFF ou F: et l'option à plusieurs caractères doit être la dernière option de la liste.

Ce qui suit sont tous des moyens équivalents 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"

Limites de longueur de chaîne de recherche
Sous 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 erreur FINDSTR: Search string too long. avec ERRORLEVEL 2.

Lorsque vous effectuez une recherche d'expression régulière, la longueur maximale de la chaîne de recherche est de 254. Une expression régulière d'une longueur comprise entre 255 et 511 entraîne une erreur FINDSTR: Out of memory avec ERRORLEVEL 2. Une longueur d'expression régulière> 511 entraîne la valeur 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 une chaîne dans une boucle "pour"? 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 ne contenant pas un seul <LF>.

Les données canalisées et l'entrée redirigée sont limitées à 8191 octets par ligne. Cette limite est une "fonctionnalité" de FINDSTR. Ce n'est pas inhérent aux pipes ou à la redirection. FINDSTR utilisant une entrée redirigée stdin ou piped ne correspondra jamais à une ligne dont la taille est> = 8k octets. Les lignes> = 8k génèrent un message d'erreur pour stderr, mais ERRORLEVEL reste égal à 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: Literal vs Regular Expression
/C:"string" - La valeur par défaut est/L littéral. La combinaison explicite de l’option/L avec/C: "chaîne" fonctionne certainement mais est redondante.

"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és 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 - Spécifiez toujours explicitement l'option /L littérale ou l'option /R expression régulière lorsque vous utilisez "string argument" ou /G:file.

BUG - Spécifier plusieurs chaînes de recherche littérales peut donner des résultats peu fiables

L'exemple simple suivant FINDSTR ne parvient pas à trouver une correspondance, même s'il le devrait.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

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

Sur la base d'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 sont de différentes longueurs
  • Une chaîne de recherche courte a un certain chevauchement avec une chaîne de recherche plus longue
  • La recherche est sensible à la casse (pas d'option /I)

À 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, voir Pourquoi cet exemple FINDSTR avec plusieurs chaînes de recherche littérales ne trouve-t-il une correspondance?

Citations et backslahses dans les arguments de ligne de commande
Remarque - Les commentaires de l'utilisateur MC ND reflètent les règles horriblement compliquées de cette section. Trois phases d'analyse distinctes sont impliquées:

  • Premièrement, cmd.exe peut nécessiter que certains guillemets soient masqués en tant que ^ "(rien à voir avec FINDSTR)
  • Suivant FINDSTR utilise le analyseur d’arguments MS C/C++ antérieur à 2008 , qui a des règles spéciales pour "et\
  • Une fois l'analyse des arguments terminée, FINDSTR considère en outre\suivi d'un caractère alphanumérique comme littéral, mais\suivi d'un caractère non alphanumérique en tant que caractère d'échappement

Le reste de cette section en surbrillance n'est pas correct à 100%. Il peut servir de guide dans de nombreuses situations, mais les règles ci-dessus sont nécessaires pour une compréhension totale.

Citation échappée dans les chaînes de recherche en ligne de commande
Les guillemets dans les chaînes de recherche en ligne de commande doivent être précédés d'une barre oblique inversée comme \". Cela est vrai tant pour les chaînes de recherche littérales que pour les expressions rationnelles. Cette information a été confirmée sur XP, Vista et Windows 7.

Remarque: vous devrez peut-être également échapper la citation pour l'analyseur CMD.EXE, mais cela n'a rien à voir avec FINDSTR. Par exemple, pour rechercher un seul devis, vous pouvez utiliser:

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

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

Mais il y a quelques cas particuliers:

Lors de la recherche de barres obliques inverses consécutives, toutes les commandes sauf la dernière doivent être protégées. La dernière barre oblique inversée peut éventuellement être échappée.

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

Rechercher une ou plusieurs barres obliques inverses avant une citation est bizarre. La logique suggérerait que la citation doit être échappée et que chacune des barres obliques inverses principales doit être échappée, mais cela ne fonctionne pas! Au lieu de cela, chaque barre oblique inversée doit être double et le guillemet est échappé normalement:

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

Comme indiqué précédemment, un ou plusieurs guillemets masqués peuvent également nécessiter un masquage avec ^ pour l'analyseur CMD .

Les informations de cette section ont été confirmées sous XP et Windows 7.

Échappement d'une barre oblique inversée dans les chaînes de recherche d'expression rationnelle en ligne de commande

  • Vista uniquement: La barre oblique inversée dans une expression rationnelle doit être soit un double échappement, comme \\\\, soit un simple échappement dans un jeu de classes de caractères tel que [\\]

  • XP et Windows 7: La barre oblique inverse dans une expression régulière peut toujours être représentée par [\\]. Il peut normalement être représenté par \\. Mais cela ne fonctionne jamais si la barre oblique inverse précède une citation échappée.

    Une ou plusieurs barres obliques inverses avant une citation masquée doivent soit être doublées, soit codées comme suit: [\\]

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

Citation échappée et barre oblique inverse dans/G: FILE chaînes de recherche littérales
Les guillemets et les barres obliques inverses autonomes dans un fichier de chaîne de recherche littérale spécifié par/G: le fichier n'a pas besoin d'être échappé, mais ils peuvent l'être.

" et \" sont équivalents.

\ et \\ sont équivalents.

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

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

Citation échappée et barre oblique inversée dans/G: Chaînes de recherche de regex FILE
Il s'agit du seul cas où les séquences d'échappement fonctionnent comme prévu sur la base de la documentation. Quote n'est pas un métacaractère regex, il ne doit donc pas être échappé (mais peut l'être). La barre oblique inverse est un métacaractère regex, il doit donc être échappé.

Limites de caractères pour les paramètres de ligne de commande - Transformation étendue ASCII
Le caractère null (0x00) ne peut apparaître dans aucune chaîne de la ligne de commande. Tout autre caractère mono-octet peut apparaître dans la chaîne (0x01 - 0xFF). Cependant, FINDSTR convertit de nombreux caractères étendus ASCII 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 étendus ASCII ne se 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 un code ASCII étendu, utilisez plutôt l'option /G:FILE.

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

Voici une liste complète des transformations de caractères ASCII étendues effectuées par FINDSTR sur les chaînes de ligne de commande. Chaque caractère est représenté sous forme de valeur de code octet décimal. Le premier code représente le caractère tel qu'il est fourni sur la ligne de commande et le second code représente le caractère en lequel il est transformé. Remarque - cette liste a été compilée sur un ordinateur américain. Je ne sais pas quel impact d'autres langages 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 tel, y compris <CR> et <LF>. Le moyen le plus simple d’inclure des caractères impairs, tels que <CR> et <LF>, consiste à les insérer dans une variable d’environnement et à utiliser l’extension différé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: options FILE et/F: 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 terminateurs de ligne qui terminent une chaîne et ne sont pas inclus dans la chaîne.

Tous les autres caractères mono-octet sont parfaitement inclus dans une chaîne.

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

Cependant, la commande TYPE convertit UTF-16LE avec BOM en un jeu de caractères simple 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 caractères ?.

Il est possible de rechercher UTF-8 tant que votre chaîne de recherche ne contient que de l'ASCII. Cependant, 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 correctement codé en UTF-8. Notez que si le fichier UTF-8 contient une nomenclature, celle-ci sera considérée comme faisant partie de la première ligne, ce qui pourrait entraîner 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 coupe 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 à travers les sauts de ligne
Comme prévu, le métacaractère . regex ne correspondra pas à <CR> ou à <LF>. Mais il est possible d'effectuer une recherche par saut de ligne à l'aide d'une chaîne de recherche en ligne de commande. Les caractères <CR> et <LF> doivent correspondre explicitement. Si une correspondance sur plusieurs lignes est trouvée, seule la 1re ligne de la correspondance est imprimée. FINDSTR double ensuite à la 2e ligne de la source et recommence la recherche - une sorte de fonction de type "regarder devant".

Supposons que TEXT.TXT a ce contenu (ce peut être un style Unix ou Windows)

A
A
A
B
A
A

Puis 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 entre 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> consiste à utiliser une expression de plage de classe de caractères regex prenant en sandwich les caractères EOL.

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

  • [<0x0C>-!] correspond à <CR>, mais également à <0x0C> et!

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

Suite de la réponse à la partie 2 ci-dessous ...

270
dbenham

Suite de la réponse de la partie 1 ci-dessus - La limite de réponse de 30 000 caractères est actuellement remplie:

Support des expressions régulières limitées (regex)
La prise en charge par FINDSTR des expressions régulières est extrêmement limitée. Si ce n'est pas dans la documentation HELP, il n'est pas pris en charge.

De plus, les expressions rationnelles prises en charge sont implémentées de manière totalement non standard, de sorte que les résultats peuvent être différents de ceux attendus, par exemple, de grep ou de Perl.

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

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

Remarque - Comme indiqué précédemment, les entrées redirigées et redirigées vers FINDSTR peuvent être précédées de <CR><LF> qui ne figure pas dans la source. Cela peut évidemment avoir une incidence sur une recherche regex utilisant $.

Toute chaîne de recherche comportant des caractères avant ^ ou après $ ne trouvera toujours pas de correspondance.

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

/ B fonctionne de la même façon que ^ au début d'une chaîne de recherche d'expression régulière.

/ E fonctionne de la même manière que $ à la fin d'une chaîne de recherche d'expression régulière.

/ X fonctionne comme si vous aviez ^ au début et $ à la fin d'une chaîne de recherche d'expression régulière.

Limite du mot regex
\< doit être le tout premier terme de la regex. La regex ne correspondra à rien si d'autres caractères le précèdent. \< correspond au tout début de l'entrée, au début d'une ligne (la position suivant immédiatement un <LF>) ou à la suite d'un caractère "non-Word". Le caractère suivant ne doit pas nécessairement être un caractère "Word".

\> doit être le dernier terme de la regex. La regex ne correspondra à rien si d'autres personnages le suivent. \> correspond à la fin de la saisie, à la position précédant immédiatement un <CR> ou à la position précédant immédiatement tout caractère "non-Word". Le caractère précédent ne doit pas nécessairement être un caractère "Word".

Voici une liste complète des caractères "non-Word", représentés par le code octet décimal. Remarque - cette liste a été compilée sur un ordinateur américain. 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

Plage de classes de caractères regex [x-y]
Les plages de classes de caractères ne fonctionnent pas comme prévu. Voir cette question: --- (pourquoi findstr ne traite-t-il pas correctement le cas (?)?
, avec cette réponse: https://stackoverflow.com/a/8767815/101205 .

Le problème est que FINDSTR ne rassemble pas les caractères en fonction de leur valeur de code octet (généralement considéré comme le code ASCII, mais ASCII est uniquement défini entre 0x00 et 0x7F). La plupart des implémentations de regex traiteraient [A à Z] comme toutes les majuscules anglais majuscules. Mais FINDSTR utilise une séquence de classement qui correspond approximativement au fonctionnement de SORT. Donc [A-Z] inclut l'alphabet anglais complet, majuscule et minuscule (sauf "a"), ainsi que les caractères alpha non anglais avec des signes diacritiques.

Vous trouverez ci-dessous une liste complète de tous les caractères pris en charge par FINDSTR, classés dans la séquence de classement utilisée par FINDSTR pour établir les plages de classes de caractères d'expression régulière. Les caractères sont représentés sous forme de valeur de code octet décimal. Je pense que la séquence de classement prend tout son sens si les caractères sont visualisés à l'aide de la page de codes 437. Remarque - cette liste a été compilée sur un ordinateur américain. 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 terme de classe de caractères regex et BUG
Non seulement FINDSTR est limité à un maximum de 15 termes de classe dans une expression rationnelle, mais il ne parvient pas à gérer 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'une fenêtre interactive Windows indiquant "L'utilitaire Find String (QGREP) a rencontré un problème et doit être fermé. Nous sommes désolés pour le désagrément." Le texte du message varie légèrement selon la version de Windows. Voici un exemple de 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]

Ce bogue a été signalé par l'utilisateur DosTips Judago ici . Cela a été confirmé sur XP, Vista et Windows 7.

Les recherches sur les expressions rationnelles échouent (et peuvent se bloquer indéfiniment) si elles incluent le code octet 0xFF (255 décimal)
Toute recherche de regex incluant le code octet 0xFF (255 décimal) échouera. Il échoue si le code d'octet 0xFF est inclus directement ou s'il est implicitement inclus dans une plage de classes de caractères. N'oubliez pas que les plages de classes de caractères FINDSTR ne regroupent pas les caractères en fonction de la valeur du code d'octet. Le caractère <0xFF> apparaît relativement tôt dans la séquence de classement entre les caractères <space> et <tab>. Ainsi, toute plage de classe de caractères incluant <space> et <tab> échouera.

Le comportement exact change légèrement en fonction de la version de Windows. Windows 7 se bloque indéfiniment si 0xFF est inclus. XP ne se bloque pas, mais il ne trouve toujours pas de correspondance et affiche parfois le message d'erreur suivant - "Le processus a tenté d'écrire dans un canal inexistant."

Je n'ai plus accès à une machine Vista, je n'ai donc pas pu tester sur Vista.

Bogue de regex: . et [^anySet] peuvent correspondre à la fin du fichier
Les méta-caractères de regex . ne doivent correspondre qu'à des caractères autres que <CR> ou <LF>. Un bogue lui permet de correspondre à la fin du fichier si la dernière ligne du fichier n'est pas terminée par <CR> ou <LF>. Cependant, le . ne correspondra pas à un fichier vide.

Par exemple, un fichier nommé "test.txt" contenant une seule ligne de x, sans mettre fin à <CR> ou <LF>, correspondra à ce qui suit:

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

Ce bogue a été confirmé sur XP et Win7.

La même chose semble être vraie pour les jeux de caractères négatifs. Quelque chose comme [^abc] correspondra à End-Of-File. Les jeux de caractères positifs tels que [abc] semblent fonctionner correctement. Je l'ai seulement testé sur Win7.

62
dbenham

findstr se bloque parfois de manière inattendue lors de la recherche de fichiers volumineux.

Je n'ai pas confirmé les conditions exactes ou la taille des limites. Je suspecte que tout fichier plus volumineux de 2 Go soit en danger.

J'ai eu des expériences mitigées avec cela, donc c'est plus que la taille du fichier. Cela ressemble à une variation sur FINDSTR se bloque sur XP et Windows 7 si l'entrée redirigée ne se termine pas par LF , mais comme démontré, ce problème particulier se manifeste lorsque l'entrée est non redirigé.

La session en ligne de commande suivante (Windows 7) montre comment findstr peut se bloquer lors de la recherche d'un fichier de 3 Go.

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>

Remarque, j'ai vérifié dans un éditeur hexadécimal que toutes les lignes sont terminées par CRLF. La seule anomalie est que le fichier est terminé avec 0x1A en raison de la façon dont copy fonctionne . Notez cependant que cette anomalie ne pose pas de problème pour les "petits" fichiers .

Avec des tests supplémentaires, j'ai confirmé ce qui suit:

  • L'utilisation de copy avec l'option /b pour les fichiers binaires empêche l'ajout du caractère 0x1A, et findstr ne reste pas bloqué sur le fichier de 3 Go.
  • Terminer le fichier de 3 Go avec un caractère différent provoque également le blocage de findstr.
  • Le caractère 0x1A ne pose aucun problème sur un "petit" fichier. (De même pour les autres caractères de fin.)
  • L'ajout de CRLF après 0x1A résout le problème. (LF par lui-même suffirait probablement.)
  • Utiliser type pour diriger le fichier dans findstr fonctionne sans accroc. (Cela peut être dû à un effet secondaire de type ou | qui insère une fin de ligne supplémentaire.)
  • L'utilisation de l'entrée redirigée < provoque également le blocage de findstr. Mais c'est prévu; comme expliqué dans post de dbenham : "une entrée redirigée doit se terminer par LF" .
6
Disillusioned

Lorsque plusieurs commandes sont entre parenthèses et que des fichiers sont redirigés vers l’ensemble du bloc:

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

... alors les fichiers restent ouverts tant que les commandes du bloc sont actives, elles peuvent donc déplacer le pointeur de fichier des fichiers redirigés. Les commandes MORE et FIND déplacent le pointeur de fichier Stdin au début du fichier avant de le traiter, de sorte que le même fichier peut être traité plusieurs fois dans le bloc. Par exemple, ce code:

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

... produit le même résultat que celui-ci:

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

Ce code:

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

... produit le même résultat que celui-ci:

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

FINDSTR est différent. il ne déplace pas le pointeur de fichier Stdin de sa position actuelle. Par exemple, ce code insère une nouvelle ligne après une ligne de recherche:

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

Nous pouvons faire bon usage de cette fonction à l’aide d’un programme auxiliaire nous permettant de déplacer le pointeur de fichier d’un fichier redirigé, comme indiqué dans cet exemple .

Ce comportement a été signalé pour la première fois par jeb à ce message .


EDIT 2018-08-18 : Nouveau bogue FINDSTR signalé

La commande FINDSTR a un bogue étrange qui se produit lorsque cette commande est utilisée pour afficher des caractères en couleur ET que la sortie d'une telle commande est redirigée vers le périphérique CON. Pour plus d'informations sur l'utilisation de la commande FINDSTR pour afficher du texte en couleur, voir cette rubrique .

Lorsque la sortie de cette forme de commande FINDSTR est redirigée vers CON, il se passe quelque chose d'étrange après la sortie du texte dans la couleur souhaitée: tout le texte après sa sortie sous forme de caractères "invisibles", bien qu'une description plus précise soit que le texte est sortie en texte noir sur fond noir. Le texte d'origine apparaîtra si vous utilisez la commande COLOR pour réinitialiser les couleurs de premier plan et d'arrière-plan de tout l'écran. Cependant, lorsque le texte est "invisible", nous pouvons exécuter une commande SET/P afin que tous les caractères saisis n'apparaissent pas à l'écran. Ce comportement peut être utilisé pour entrer des mots de passe.

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"
6
Aacini

Je voudrais signaler un bogue concernant la section Source des données à rechercher dans la première réponse lorsque vous utilisez en dash ( -) ou em dash (-) dans le nom du fichier.

Plus précisément, si vous êtes sur le point d'utiliser la première option - noms de fichiers spécifiés en tant qu'arguments , le fichier ne sera pas trouvé. Dès que vous utilisez l’option 2 - stdin via la redirection ou 3 - flux de données à partir d’un tuyau , findstr trouvera le fichier.

Par exemple, ce script batch simple:

echo off
chcp 1250 > nul
set INTEXTFILE1=filename with – dash.txt
set INTEXTFILE2=filename with — dash.txt

rem 3 way of findstr use with en dashed filename
echo.
echo Filename with en dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE1%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE1%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE1%" | findstr .
echo.
echo.
rem The same set of operations with em dashed filename
echo Filename with em dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE2%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE2%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE2%" | findstr .
echo.

pause

imprimera:

Nom de fichier avec tiret:

  1. Comme argument
    FINDSTR: impossible d'ouvrir le nom du fichier avec - dash.txt

  2. En tant que stdin via redirection
    Je suis le fichier avec un tiret.

  3. Comme flux de données à partir d'un tuyau
    Je suis le fichier avec un tiret.

Nom de fichier avec tiret:

  1. Comme argument
    FINDSTR: impossible d'ouvrir le nom du fichier avec - dash.txt

  2. En tant que stdin via redirection
    Je suis le fichier avec un tiret em.

  3. Comme flux de données à partir d'un tuyau
    Je suis le fichier avec un tiret em.

J'espère que ça aide.

M.

2
matro