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

la commande Windows FINDSTR est horriblement documentée. Il y a de l'aide en ligne de commande disponible par FINDSTR /? , ou HELP FINDSTR , mais elle est terriblement insuffisante. Il y a un peu plus de documentation en ligne à https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

il y a de nombreuses caractéristiques et limitations de FINDSTR qui ne sont même pas suggérées dans la documentation. Ils ne pouvaient être anticipé sans connaissance préalable et / ou expérimentation minutieuse.

donc la question Est - quelles sont les caractéristiques et les limites de FINDSTR non documentées?

Le but de cette question est de fournir un référentiel de nombreux sans-papiers fonctions:

A) les développeurs peuvent profiter pleinement des fonctionnalités qui sont là.

B) les développeurs ne perdent pas leur temps je me demande pourquoi quelque chose ne fonctionne pas alors que c'est normal.

veuillez vous assurer de connaître la documentation existante avant de répondre. Si l'information est couverte par L'aide, alors elle n'a pas sa place ici.

ce n'est pas non plus un endroit pour montrer les utilisations intéressantes de FINDSTR. Si une personne logique pouvait anticiper le comportement d'un usage particulier de FINDSTR basé sur la documentation, alors il 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 basé sur des informations contenues dans des réponses existantes, alors encore une fois, il n'appartient pas ici.

168
demandé sur dbenham 2012-01-13 05:39:15

6 réponses

préface

une grande partie de l'information contenue dans cette réponse a été recueillie à partir d'expériences réalisées sur une machine Vista. Sauf mention 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. Il fait allusion au fait que les lignes correspondantes sont imprimées, mais rien de plus.

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

nom du fichier: lineNumber: lineOffset: text

nom du fichier: = le nom du fichier contenant le correspondance de la ligne. Le nom du fichier n'est pas imprimé si la requête était explicitement pour un seul fichier, ou si la recherche a été faite par piped input ou redirigée input. Une fois imprimé, le nom du fichier inclura toujours toute information de chemin fournie. Des informations supplémentaires sur le chemin seront ajoutées si l'option /S est utilisée. L'imprimé chemin est toujours par rapport à la condition chemin, ou relatif au répertoire courant si aucune condition.

Note - le préfixe du nom de fichier peut être évité lorsque recherche de plusieurs fichiers à l'aide des caractères génériques non standard (et mal documentés) < et > . Les règles exactes pour le fonctionnement de ces caractères génériques peuvent être trouvées ici . Enfin, vous pouvez regarder cet exemple de la façon dont les caractères génériques non standard fonctionnent avec FINDSTR .

numéro de ligne: = le numéro de ligne du ligne correspondante représentée par une valeur décimale avec 1 représentant la première ligne de l'entrée. Seulement imprimé si l'option /N est spécifiée.

lineOffset: = décalage décimal du début de la ligne correspondante, avec 0 représentant le 1er caractère de la première ligne. Seulement imprimé si l'option /O est spécifiée. C'est et non le décalage du match à l'intérieur de la ligne. C'est le nombre d'octets à partir du début du fichier pour le début de la ligne.

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

FINDSTR "^" FILE >FILE_COPY

Plus de contrôle les caractères 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 comme des points (périodes) sur l'écran. Les caractères de contrôle suivants sont des exceptions; ils s'affichent comme eux - mêmes: 0x09 Tab, 0x0A LineFeed, 0x0b Vertical Tab, 0x0c form Feed, 0x0D Carriage Return.

XP FINDSTR convertit aussi un certain nombre de caractères ASCII étendus en points. Les caractères ASCII étendus qui s'affichent sous 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 "Character limits for command line parameters-Extended ASCII transformation " , plus loin dans ce post

Les caractères de contrôle

et les ASCII étendus ne sont pas convertis en points sur XP si la sortie est pipée, redirigée vers un fichier, ou dans une clause FOR IN ().

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

Return Codes (ERRORLEVEL))

  • 0 (succès) La correspondance
    • a été trouvée dans au moins une ligne d'au moins un fichier.
  • 1 (défaillance)
    • aucune correspondance n'a été trouvée dans aucune ligne d'un fichier.
    • couleur non valide spécifiée par /A:xx option
  • 2 (Erreur)
    • options incompatibles /L et /R toutes deux spécifiées
    • argument manquant après /A: , /F: , /C: , /D: , ou /G:
    • fichier spécifié par /F:file ou /G:file non trouvé
  • 255 (erreur)

Source de données pour la recherche (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 comme arguments et/ou en utilisant l'option /F:file .

  • stdin via la redirection de findstr "searchString" <file

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

Les Arguments / options ont priorité sur la redirection, qui a priorité sur les données pipées.

Les arguments

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, alors seule la dernière est utilisée. Les jokers sont autorisés dans les arguments nom de fichier, mais pas dans le fichier pointé par /F:file .

Source des chaînes de recherche (mis à jour sur la base d'essais 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, alors seule la dernière est utilisée. Si /G:file ou /C:string est utilisé, alors tous les arguments non-optionnels sont considérés comme des fichiers à rechercher. Si ni /G:file ni /C:string n'est utilisé, alors la première non-option l'argument est traité comme une liste délimitée par un espace des termes de recherche.

les noms de fichiers ne doivent pas être cités dans le fichier lorsque vous utilisez 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 /F:files.txt de FINDSTR exige que les noms de fichiers se trouvent dans les fichiers.txt ne doit pas être cité. Le fichier ne sera pas trouvé, si le nom est citer.

BUG - Court 8.3 les noms de fichiers peuvent briser le /D et /S options

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 courant contient les fichiers non vides suivants:

b1.txt
b.txt2
c.txt

la commande suivante va trouver avec succès les 3 fichiers:

findstr /m "^" *.txt

b.txt2 correspond parce que le nom court correspondant B9F64~1.TXT correspond. Ceci est compatible avec le comportement de toutes les autres commandes Windows.

mais un bug 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 bug empêche b.txt2 d'être trouvé, ainsi que tous les noms de fichiers qui trient après b.txt2 dans le même répertoire. Des fichiers supplémentaires qui trient avant, comme a.txt , sont trouvés. Les fichiers supplémentaires qui trient 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 avec succès la recherche dans un dossier enfant après avoir échoué à trouver des fichiers dans le parent, mais une fois que le bogue provoque un nom de fichier court à manquer dans l'enfant, puis tous les fichiers suivants dans ce dossier enfant seraient également manqués.

les commandes fonctionnent sans bogue 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 bogue. Toutes les instances de comportement de bugged que j'ai vu impliquent une extension qui est plus longue que 3 caractères avec un nom court 8.3 qui commence de la même façon qu'un nom normal qui ne nécessite pas un nom 8.3.

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

caractères Non imprimables et /P option

L'option /P fait sauter à FINDSTR tout fichier qui contient l'un des codes décimaux suivants:

0-7, 14-25, 27-31.

Put d'une autre manière, l'option /P ne sautera que les fichiers qui contiennent 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 sauter le fichier.

les entrées canalisées et redirigées peuvent avoir <CR><LF> applied

Si l'entrée est pipée et que le dernier caractère du flux n'est pas <LF> , alors FINDSTR ajoutera automatiquement <CR><LF> à l'entrée. Ceci a été confirmé sur XP, Vista et Windows 7. (j'avais l'habitude de penser que la pipe Windows était responsable de la modification de l'entrée, mais j'ai depuis découvert que FINDSTR fait réellement la modification.)

le il en va de même pour les entrées redirigées 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 ne modifient pas les entrées redirigées.

FINDSTR se bloque sur XP et Windows 7 si redirigé entrée ne prend pas fin avec <LF>

C'est une vilaine "fonctionnalité" sur XP et Windows 7. Si le dernier caractère de un fichier utilisé comme entrée redirigée ne se termine pas avec <LF> , alors FINDSTR sera suspendu indéfiniment une fois qu'il atteint la fin du fichier redirigé.

la dernière ligne de données canalisées peut être ignorée si elle est constituée d'un seul caractère

Si L'entrée est pipée et que la dernière ligne se compose 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 de <LF> ne correspond pas, mais la deuxième commande avec 2 caractères fonctionne bien, comme le fait la troisième commande qui a un caractère avec terminaison newline.

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

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

> echo x| findstr "^"
x

Rapporté par DosTips utilisateur Éponge Ventre nouvelle findstr bug . Confirmé sur XP, Windows 7 et Windows 8. Je n'ai pas encore entendu parler de Vista. (Je n'ai plus de Vista à tester).

syntaxe D'Option

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

suivantes sont équivalentes façons d'exprimer un cas insensible recherche regex pour n'importe quelle ligne qui contient à la fois "hello" et "goodbye" 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"




Sur Vista La longueur maximale permise pour une chaîne de recherche simple est de 511 octets. Si une chaîne de recherche dépasse 511, alors le résultat est une erreur FINDSTR: Search string too long. avec ERRORLEVEL 2.

pour une recherche d'expression régulière, la longueur maximale de la chaîne de recherche est 254. Une expression régulière avec une longueur entre 255 et 511 résultera en une erreur FINDSTR: Out of memory avec ERRORLEVEL 2. Une longueur d'expression régulière >511 entraîne l'erreur FINDSTR: Search string too long. .

sur Windows XP la longueur de la chaîne de recherche est apparemment plus courte. Findstr d'erreur: "la Recherche d'une chaîne trop longue": Comment extraire et de correspondance de sous-chaîne dans la boucle "for"? La limite de XP est de 127 octets pour les recherches littérales et regex.

limites de longueur de ligne

Les fichiers spécifiés comme 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é effectuées avec succès contre 128MB fichier qui ne contient pas un seul .

données acheminées et entrées redirigées est limité à 8191 octets par ligne. Cette limite est une "caractéristique" de FINDSTR. Il n'est pas inhérent aux pipes ou à la redirection. FINDSTR utilisant STDIN redirigé ou entrée pipée ne correspondra jamais à aucune ligne qui est >=8K bytes. Lines >= 8k génèrent un message d'erreur à stderr, mais ERRORLEVEL est toujours 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" - the default is / L literal. 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 première chaîne de recherche. (rappelez-vous que est utilisé pour délimiter les chaînes de recherche.) si la première chaîne de recherche est une régulière valide expression qui contient au moins un méta-caractère non échappé, alors 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 littérales. Par exemple, "51.4 200" sera traité comme deux expressions régulières parce que la première chaîne contient un point non échappé, tandis que "200 51.4" sera traité comme deux littérales parce que la première chaîne ne contient pas de méta-caractères.

/G:file - La valeur par défaut dépend de la le contenu de la première ligne non vide dans le fichier. Si la première chaîne de recherche est une expression régulière valide qui contient au moins un méta-caractère non échappé, alors 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 littérales.

recommandation - toujours spécifier explicitement /L option littérale ou /R option d'expression régulière en utilisant "string argument" ou /G:file .

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

l'exemple simple suivant de FINDSTR ne trouve pas de correspondance, même si elle devrait.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

ce bug a été confirmé sur Windows Server 2003, Windows XP, Vista et Windows 7.

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

  • la recherche utilise plusieurs chaînes de recherche littérale
  • Les chaînes de recherche sont de longueurs différentes
  • une chaîne de recherche courte a un certain degré de chevauchement avec une chaîne de recherche plus longue
  • la recherche est sensible à la casse (pas d'option /I )

dans chaque échec que j'ai vu, il est toujours l'un des des chaînes de recherche plus courtes qui échouent.

pour plus d'informations, voir pourquoi cet exemple FINDSTR avec plusieurs chaînes de recherche littérale ne trouve-t-il pas une correspondance?

guillemets et backslahses dans les arguments en ligne de commande-Note:

L'information contenue dans cette section en surbrillance n'est pas exacte à 100%. Après avoir écrit ceci section, l'utilisateur MC ND m'a indiqué une référence qui documente comment la bibliothèque Microsoft C/C++ se comporte les paramètres . Il est terrifiant compliqué, mais il semble prédire avec précision les règles backslash et quote pour les arguments en ligne de commande FINDSTR. Je vous recommandons d'utiliser les informations ci-dessous comme guide, mais si vous voulez des informations plus précises, se référer au lien.

échapper citation dans la ligne de commande chaînes de recherche

les guillemets dans les chaînes de recherche en ligne de commande doivent être échappés avec des antislash comme \" . Ceci est vrai pour les chaînes de recherche littérale et regex. Ce l'information a été confirmée sur XP, Vista, et Windows 7.

Note: La citation peut également devoir être évitée pour le CMD.EXE parser, mais ça n'a rien à voir avec FINDSTR. Par exemple, pour rechercher un apostrophe, vous pourriez utiliser:

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

barre Oblique inverse d'Échappement à l'intérieur de la ligne de commande littérale des chaînes de recherche

barre Oblique inverse dans un littéral chaîne de recherche peut normalement être représenté comme \ ou \ . Ils sont généralement équivalent. (il peut y avoir des cas à Vista où le revers doit toujours être échappé, mais je ne plus longtemps avoir une machine Vista à l'essai) .

mais il y a quelques cas particuliers:

lors de la recherche de backslashs consécutifs, tous sauf le dernier doit être échapper. Le dernier revers peut éventuellement être échappé.

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

la recherche d'un ou de plusieurs antislashs avant une citation est bizarre. Logique suggère que la citation doit être échappé, et chacun des principaux backslashs devrait être échappé, mais cela ne fonctionne pas! Plutôt, chacun des backslashs principaux doit être double échappée, et la citation s'échappe normalement:

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

comme nous l'avons noté précédemment, une ou plusieurs citations évadées peuvent également nécessiter une fuite avec ^ pour le CMD parser

les informations dans cette section ont été confirmées sur XP et Windows 7.

barre Oblique inverse d'Échappement à l'intérieur de la ligne de commande regex chaînes de recherche

  • Vista: barre Oblique inverse dans une regex doit être soit double échappé comme \\ , ou bien seul échappé au sein d'une classe de caractères définie comme [\]

  • XP et Windows 7: Backslash dans un regex peut toujours être représenté comme [\] . Elle peut normalement être représentée par \ . Mais ce n'a jamais fonctionne si le revers précède un échappé à la citation.

    un ou plusieurs backslashs avant une citation échappée doit être double échappée, ou alors codée comme [\]

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

escapade Quote and Backlash within / G:FILE literal search strings

Les guillemets et les antislashes indépendants dans un fichier de recherche littéral spécifié par /G:file 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 \\, alors au moins l' leader de la barre oblique inverse doit être échappé. \\ et \\ .

si l'intention est de trouver\", alors au moins le premier revers doit être échappé. Les deux \" et \\" travail.

s'Échappant de Devis et de barre Oblique inverse à l'intérieur de /G:FICHIER regex chaînes de recherche

C'est le seul cas où les séquences d'échappement fonctionnent comme prévu sur la base de la documentation. Devis pas un metacharacter regex, donc il n'a pas besoin d'être échappé (mais peut l'être). Backslash est un metacharacter regex, donc il doit être échappé.

la limite de Caractères pour les paramètres de ligne de commande - ASCII Étendu transformation

Le caractère nul (0x00) ne peut apparaître dans aucune chaîne sur la ligne de commande. N'importe quel autre caractère d'octet simple peut apparaître dans la chaîne de caractères (0x01 - 0xFF). Cependant, FINDSTR convertit de nombreux caractères ASCII étendus il trouve dans les paramètres de la ligne de commande d'autres caractères. Cela a un impact majeur de deux façons:

1) de nombreux caractères ASCII étendus ne correspondront 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 ASCII étendu, l'option /G:FILE doit être utilisée à la place.

2) FINDSTR peut ne parviennent pas à trouver un fichier si le nom contient des étendues Les caractères ASCII et le nom du fichier sont spécifiés sur la ligne de commande. Si un fichier à rechercher contient des 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 exécute sur des chaînes de lignes de commande. Chaque caractère est représenté par le code décimal. Le premier code représente le caractère tel que fourni sur la ligne de commande, et le deuxième code représente le personnage est transformé en. 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 tel, y compris <CR> et LF> . La façon la plus simple d'inclure des caractères impairs comme <CR> et <LF> est de les insérer dans une variable d'environnement et d'utiliser l'expansion retardée dans le argument en ligne de commande.

la limite de Caractères pour les chaînes trouvées dans les fichiers spécifiés par /G:FICHIER et /F:FICHIER options

Le caractère nul (0x00) peut apparaître dans le fichier, mais il fonctionne comme le terminator C string. Tous les caractères après un caractère nul sont traités comme une chaîne différente comme s'ils étaient sur une autre ligne.

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

tous les autres caractères simples sont parfaitement inclus dans une chaîne.

recherche de fichiers Unicode

FINDSTR ne peut pas rechercher correctement la plupart des Unicodes (UTF-16, UTF-16LE, UTF-16BE, UTF-32) parce qu'il ne peut pas rechercher des octets nul et Unicode contient généralement beaucoup nul octets.

cependant, la commande TYPE convertit UTF-16LE avec BOM en un seul jeu de caractères octets, ainsi 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 code active seront convertis en ? caractères.

Il est possibilité de rechercher UTF-8 tant que votre chaîne de recherche ne contient que ASCII. Cependant, la sortie de la console de n'importe quel caractère UTF-8 à plusieurs octets ne sera pas correcte. Mais si vous redirigez la sortie vers un fichier, alors le résultat sera correctement encodé UTF-8. Notez que si le fichier UTF-8 contient un BOM, alors le BOM sera considéré 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 pour rechercher des caractères UTF-8 à plusieurs octets si vous mettez votre chaîne de recherche dans un fichier de recherche encodé UTF-8 (sans BOM), et utilisez l'option /G.

Fin De Ligne

FINDSTR casse les lignes immédiatement après chaque . La présence ou l'absence de n'a aucun impact sur les sauts de ligne.

la Recherche à travers des sauts de ligne

Comme attendu, le metacharacter regex . ne correspondra pas à ou . Mais il est possible de chercher à travers une rupture de ligne en utilisant une chaîne de recherche en ligne de commande. Les caractères et < LF> doivent être appariés explicitement. Si une correspondance multi-lignes est trouvée, seule la première ligne de la correspondance est imprimée. FINDSTR revient ensuite à la deuxième ligne de la source et recommence la recherche - une sorte de fonction de type "look ahead".

suppose texte.TXT a ces contenu (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 des sauts de ligne en utilisant l'option /G:FILE est imprécise parce que la seule façon de faire correspondre ou est par l'intermédiaire d'une expression de portée de classe de caractères regex qui Sandwich les caractères EOL.

  • [<TAB>-<0x0B>] les allumettes , mais il correspond aussi à < TAB> et <0x0B>

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

    Note-ce qui précède sont des représentations symboliques du flux d'octets regex puisque je ne peux pas représenter graphiquement les caractères.

la réponse se poursuit dans la partie 2 ci-dessous...

257
répondu dbenham 2017-09-25 15:04:50

suite de la partie 1 au-dessus de - j'ai rencontré la limite de réponse de 30 000 caractères: - (

Limité d'Expressions Régulières (regex) Support

Le support de FINDSTR pour les expressions régulières est extrêmement limité. Si elle n'est pas dans la documentation D'aide, elle n'est pas supportée.

au-delà de cela, les expressions regex qui sont supportées sont mis en œuvre d'une manière complètement non standard, de sorte que les résultats peuvent être différents que ce qui serait attendu venant de quelque chose comme grep ou perl.

ancrages de position de ligne Regex ^ et $

^ correspond au début du flux d'entrée ainsi qu'à toute position immédiatement après un . Comme FINDSTR casse aussi les lignes après , un simple regex de "^" correspondra toujours à toutes les lignes d'un fichier, même un fichier binaire.

$ correspond à toute position qui précède immédiatement a <CR>. Cela signifie qu'une chaîne de recherche regex contenant $ ne correspondra jamais à aucune ligne d'un fichier texte de style Unix, pas plus qu'elle ne correspondra à la dernière ligne d'un fichier texte Windows s'il manque le marqueur de fin de vie de .

Note - Comme nous l'avons déjà mentionné, les entrées acheminées et redirigées vers FINDSTR peuvent avoir <CR><LF> ajouté 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 $ sera toujours incapable de trouver une correspondance.

Positional Options /B /E / X

Les options de position fonctionnent de la même façon que ^ et $ , sauf qu'elles fonctionnent aussi pour des chaînes de recherche littérales.

/B fonctions la même chose que ^ au début d'une regex chaîne de recherche.

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

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

limite des mots Regex

\< ça doit être le premier mandat du regex. La regex sera ne correspond à rien si d'autres caractères le précèdent. \< correspond soit au début de l'entrée, soit au début d'une ligne (la position qui suit immédiatement un ), soit à la position qui suit immédiatement un caractère" non-word". Le caractère suivant n'a pas besoin d'être un "mot" de caractère.

\> doit être le dernier terme du regex. Le regex ne correspondra à rien si d'autres caractères le suivent. \> correspond à soit la fin de la saisie, la position immédiatement avant un , ou la position immédiatement avant tout caractère "non-word". Le caractère précédent ne doit pas nécessairement être un caractère "mot".

Voici une liste complète de caractères "non-word", représentés par le code 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

Regex classe de personnage intervalle [x-y]

Les gammes de classes de caractères ne fonctionnent pas comme prévu. Voir la question: pourquoi findstr ne traite-t-il pas les cas correctement (dans certaines circonstances)? , ainsi que cette réponse: https://stackoverflow.com/a/8767815/1012053 .

le problème est que FINDSTR ne collate pas les caractères par leur code octet (généralement considéré comme le code ASCII, mais ASCII est seulement défini de 0x00-0x7F). La plupart des implémentations de regex traiteraient [A-Z] comme toutes les majuscules anglaises. Mais FINDSTR utilise une séquence de collation qui correspond à peu près à la façon dont SORT fonctionne. Ainsi [A-Z] comprend l'alphabet anglais complet, en majuscules et en minuscules (sauf pour "a"), ainsi que des caractères alpha non-anglais avec des signes diacritiques.

ci-dessous est une liste complète de tous les caractères supportés par FINDSTR, triés dans la séquence de collation utilisé par FINDSTR pour établir les plages de classes de caractères regex. Les caractères sont représentés par leur code décimal. Je crois que la séquence de collation 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

Regex classe de caractères limite de durée et BUG

Non seulement FINDSTR est limité à un maximum de 15 termes de classe de caractères dans une regex, mais il ne gère pas correctement une tentative de dépasser la limite. L'utilisation de 16 termes de classe de caractère ou plus résulte en une fenêtre interactive pop up déclarant "trouver chaîne (QGREP) utilitaire a rencontré un problème et doit fermer. Nous sommes désolés pour la gêne occasionnée." le texte du message varie légèrement selon la version de Windows. Voici un exemple de FINDSTR qui va l'échec:

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 bug a été rapporté par L'utilisateur DosTips Judago ici . Il a été confirmé sur XP, Vista, et Windows 7.

les recherches Regex échouent (et peuvent être suspendues indéfiniment) si elles incluent le code octet 0xFF (décimal 255)

Toute recherche regex incluant le code byte 0xff (décimal 255) échouera. Il échoue si le code de byte 0xFF est inclus directement, ou s'il est implicitement inclus dans une classe de caractère gamme. Rappelez-vous que les plages de classes de caractères FINDSTR ne collatent pas les caractères basés sur la valeur du code octet. Le caractère <0xFF> apparaît relativement tôt dans la séquence de collation entre les caractères <space> et <tab> . Ainsi, toute plage de classe de caractères qui inclut à la fois <space> et <tab> sera un échec.

le comportement exact change légèrement selon la version de Windows. Windows 7 est suspendu indéfiniment si 0xFF est inclus. XP ne pend pas, mais il n'arrive pas toujours à trouver une correspondance, et imprime parfois le message d'erreur suivant - "le processus a essayé d'écrire à un tuyau inexistant."

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

Regex bug: . et [^anySet] peut correspondre à Fin-De-Fichier

La regex . méta-caractère ne doit correspondre à n'importe quel caractère autre que <CR> ou <LF> . Il y a un bug qui permet de faire correspondre la fin du fichier si la dernière ligne du fichier n'est pas terminée par <CR> ou <LF> . Cependant, le . ne correspond pas à un fichier vide.

Par exemple, un fichier nommé "test.txt" contenant une seule ligne de x , sans y mettre fin <CR> ou <LF> , permettra de faire correspondre les éléments suivants:

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

ce bug 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] correspond à la fin du fichier. Des jeux de caractères positifs comme [abc] semblent bien fonctionner. Je ne l'ai testé que sur Win7.

57
répondu dbenham 2017-05-23 12:34:59

findstr est parfois suspendu de façon inattendue lors de la recherche de gros fichiers.

Je n'ai pas confirmé les conditions exactes ou les tailles limites. Je pense que n'importe quel fichier plus gros de 2 Go peut être en danger.

j'ai eu des expériences mélangées avec cela, il est donc plus que la taille du fichier. Cela ressemble à cela peut être une variation sur FINDSTR accroche sur XP et Windows 7 Si l'entrée redirigée ne se termine pas avec LF , mais comme démontré cette un problème particulier se manifeste lorsque l'entrée est et non redirigé.

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

C:\Data\Temp14-04>echo 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890> T100B.txt

C:\Data\Temp14-04>for /L %i in (1,1,10) do @type T100B.txt >> T1KB.txt

C:\Data\Temp14-04>for /L %i in (1,1,1000) do @type T1KB.txt >> T1MB.txt

C:\Data\Temp14-04>for /L %i in (1,1,1000) do @type T1MB.txt >> T1GB.txt

C:\Data\Temp14-04>echo find this line>> T1GB.txt

C:\Data\Temp14-04>copy T1GB.txt + T1GB.txt + T1GB.txt T3GB.txt
T1GB.txt
T1GB.txt
T1GB.txt
        1 file(s) copied.

C:\Data\Temp14-04>dir
 Volume in drive C has no label.
 Volume Serial Number is D2B2-FFDF

 Directory of C:\Data\Temp14-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\Temp14-04>rem Findstr on the 1GB file does not hang

C:\Data\Temp14-04>findstr "this" T1GB.txt
find this line

C:\Data\Temp14-04>rem On the 3GB file, findstr hangs and must be aborted... even though it clearly reaches end of file

C:\Data\Temp14-04>findstr "this" T3GB.txt
find this line
find this line
find this line
^C
C:\Data\Temp14-04>

Note, j'ai vérifié dans un éditeur hexadécimal que toutes les lignes se terminent par CRLF . La seule anomalie est que le dossier est terminé avec 0x1A en raison de la voie copy fonctionne . Note cependant, que cette anomalie ne cause pas de problème sur les "petits" fichiers .

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

  • en utilisant copy avec l'option /b pour les fichiers binaires empêche l'ajout du caractère 0x1A , et findstr ne tient pas sur le fichier de 3 Go.
  • clôturant le fichier 3GO avec un autre le caractère fait aussi pendre un findstr .
  • le caractère 0x1A ne cause aucun problème sur un "petit" fichier. (De même pour les autres caractères terminants.)
  • L'ajout de CRLF après 0x1A résout le problème. ( LF en soi suffirait probablement.)
  • utilisant type pour Piper le fichier dans findstr travaux sans pendaison. (Cela peut être dû à un effet secondaire de type ou | qui insère un supplément de Fin De Ligne.)
  • Utilisation redirigé entrée < provoque aussi findstr à accrocher. , Mais c'est prévu; comme expliqué dans dbenham post : "redirection d'entrée doit se terminer par LF " .
5
répondu Disillusioned 2017-05-23 12:10:54

lorsque plusieurs commandes sont incluses entre parenthèses et qu'il y a des fichiers redirigés vers le bloc entier:

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

... puis les fichiers restent ouverts tant que les commandes du bloc sont actives, de sorte que les commandes peuvent déplacer le pointeur de fichier des fichiers redirigés. Les deux 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 à l'intérieur du bloc. Par exemple, ce code:

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

... produire 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

... produire 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 pas déplacer 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 bonne utilisation de cette fonction avec l'aide d'un programme auxiliaire qui nous permettent de déplacer le pointeur de fichier d'un fichier redirigé, comme indiqué dans cet exemple .

ce comportement a été rapporté pour la première fois par jeb à ce post .


EDIT 2018-08-18 : New FINDSTR bug reported

le La commande FINDSTR a un bug étrange qui se produit lorsque cette commande est utilisée pour afficher les caractères en couleur et la sortie d'une telle commande est redirigée vers CON device. Pour plus de détails sur la façon D'utiliser la commande FINDSTR pour afficher le texte en couleur, voir ce sujet .

lorsque la sortie de cette forme de commande FINDSTR est redirigée vers CON, quelque chose d'étrange se produit après que le texte est sorti dans la couleur désirée: tout le texte après qu'il est sorti comme des caractères "invisibles" , bien qu'une description plus précise que le texte est sortie que le texte noir sur fond noir. Le texte original apparaîtra si vous utilisez la commande COLOR pour réinitialiser les couleurs de premier plan et de fond de l'écran entier. Cependant, lorsque le texte est "invisible", nous pouvons exécuter une commande SET /P, de sorte que tous les caractères entrés 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%"
5
répondu Aacini 2018-08-19 02:13:31

j'aimerais signaler un bug concernant la section Source de données pour rechercher dans la première réponse en utilisant en dash ( – ) ou em dash ( - ) dans le nom de fichier.

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

par exemple, ce script de lot 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

imprime:

nom du fichier avec en dash:

  1. Comme argument

    FINDSTR: Impossible d'ouvrir le fichier avec tableau de bord.txt

  2. Comme stdin via redirection

    je suis le fichier avec un tiret.

  3. comme faisceau de données d'un tuyau

    je suis le fichier avec un tiret.

nom de fichier avec un tiret cadratin:

  1. Comme argument

    FINDSTR: Impossible d'ouvrir le fichier avec tableau de bord.txt

  2. Comme stdin via la redirection de

    je suis le fichier avec un tiret cadratin.

  3. comme faisceau de données d'un tuyau

    je suis le fichier avec un tiret em.

j'Espère que ça aide.

M.

2
répondu matro 2016-12-18 17:25:03

/d conseil pour les répertoires multiples: mettez votre liste de répertoires avant la chaîne de recherche. Tout cela fonctionne:

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

comme prévu, le chemin est relatif à l'emplacement si vous ne démarrez pas les répertoires avec \ . Entourer le chemin avec " est facultatif s'il n'y a pas d'espaces dans les noms de répertoires. La fin \ est optionnelle. La sortie de l'emplacement inclura n'importe quel chemin que vous lui donnez. Il fonctionne avec ou sans environnantes la liste des répertoires avec " .

-1
répondu gordon 2015-01-22 20:11:26