Was sind die undokumentierten Funktionen und Einschränkungen des Windows-Befehls FINDSTR?

188

Der Windows-Befehl FINDSTR ist schrecklich dokumentiert. Es gibt eine sehr grundlegende Befehlszeilenhilfe, die über FINDSTR /?oder verfügbar ist HELP FINDSTR, die jedoch absolut unzureichend ist. Unter https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

Es gibt viele FINDSTR-Funktionen und -Einschränkungen, auf die in der Dokumentation nicht einmal hingewiesen wird. Sie könnten auch nicht ohne Vorkenntnisse und / oder sorgfältiges Experimentieren erwartet werden.

Die Frage ist also: Was sind die undokumentierten FINDSTR-Funktionen und -Einschränkungen?

Der Zweck dieser Frage besteht darin, ein One-Stop-Repository der vielen undokumentierten Funktionen bereitzustellen, damit:

A) Entwickler können die vorhandenen Funktionen voll ausnutzen.

B) Entwickler verschwenden keine Zeit damit, sich zu fragen, warum etwas nicht funktioniert, wenn es so scheint, wie es sollte.

Bitte stellen Sie sicher, dass Sie die vorhandene Dokumentation kennen, bevor Sie antworten. Wenn die Informationen von der HILFE abgedeckt werden, gehören sie nicht hierher.

Dies ist auch kein Ort, um interessante Anwendungen von FINDSTR zu zeigen. Wenn eine logische Person das Verhalten einer bestimmten Verwendung von FINDSTR basierend auf der Dokumentation vorhersehen könnte, dann gehört es nicht hierher.

In diesem Sinne gehört eine logische Person, die das Verhalten einer bestimmten Verwendung basierend auf Informationen, die in vorhandenen Antworten enthalten sind, vorhersehen könnte, nicht hierher.

Dbenham
quelle
15
Oder alternativ können Sie den crappy undokumentierte MS - Dienstprogramm zusammen Graben und Installation / Verwendung , grepdie sich sehr gut verstanden und dokumentiert :-) Siehe stackoverflow.com/questions/2635740/... zum Beispiel.
Paxdiablo
17
Wenn Sie in der Lage sind, etwas anderes als FINDSTR zu verwenden, ist dies auf jeden Fall sehr zu empfehlen. Einige Personen befinden sich jedoch in Umgebungen, in denen Dienstprogramme von Drittanbietern verboten sind.
Dbenham
4
Keine Beleidigung genommen. Ich habe ernsthaft darüber nachgedacht, meinen eigenen FINDSTR-Haftungsausschluss einzufügen, der Ihrem Kommentar ähnlich ist! :)
Dbenham
41
Ich bin schockiert und enttäuscht, jemand würde diese Frage "Nicht konstruktiv" finden und abstimmen, um zu schließen. Es wurde viel über die Frage nachgedacht, um "Meinungen, Debatten, Argumente, Umfragen oder erweiterte Diskussionen" zu vermeiden. Die Frage wurde 3,5 Monate lang gestellt, und keines der genannten Negative ist aufgetreten. Die gepaarte Antwort ist voller Fakten und erfordert viele Stunden sorgfältiger Forschung und Experimente.
Dbenham
6
Einige Leser interessieren sich möglicherweise für den historischen Kontext des Befehls findstr
Harry Johnston

Antworten:

279

Vorwort
Ein Großteil der Informationen in dieser Antwort wurde anhand von Experimenten gesammelt, die auf einem Vista-Computer ausgeführt wurden. Sofern nicht ausdrücklich anders angegeben, habe ich nicht bestätigt, ob die Informationen für andere Windows-Versionen gelten.

FINDSTR-Ausgabe
In der Dokumentation wird die Ausgabe von FINDSTR nie erläutert. Es spielt auf die Tatsache an, dass übereinstimmende Linien gedruckt werden, aber nichts weiter.

Das Format der übereinstimmenden Zeilenausgabe lautet wie folgt:

Dateiname: lineNumber: lineOffset: text

wo

Dateiname: = Der Name der Datei, die die übereinstimmende Zeile enthält. Der Dateiname wird nicht gedruckt, wenn die Anforderung explizit für eine einzelne Datei war oder wenn über Pipeline-Eingaben oder umgeleitete Eingaben gesucht wurde. Beim Drucken enthält der Dateiname immer alle bereitgestellten Pfadinformationen. Zusätzliche Pfadinformationen werden hinzugefügt, wenn die/SOption verwendet wird. Der gedruckte Pfad ist immer relativ zum angegebenen Pfad oder relativ zum aktuellen Verzeichnis, wenn keiner angegeben ist.

Hinweis - Das Dateinamenpräfix kann beim Durchsuchen mehrerer Dateien mithilfe der nicht standardmäßigen (und schlecht dokumentierten) Platzhalter < und vermieden werden >. Die genauen Regeln für die Funktionsweise dieser Platzhalter finden Sie hier . Schließlich können Sie sich dieses Beispiel ansehen, wie die nicht standardmäßigen Platzhalter mit FINDSTR funktionieren .

lineNumber: = Die Zeilennummer der übereinstimmenden Zeile, die als Dezimalwert dargestellt wird, wobei 1 die erste Zeile der Eingabe darstellt. Wird nur gedruckt, wenn die/NOption angegeben ist.

lineOffset: = Der Dezimalbyte-Offset des Beginns der übereinstimmenden Zeile, wobei 0 das 1. Zeichen der 1. Zeile darstellt. Wird nur gedruckt, wenn die/OOption angegeben ist. Dies ist nicht der Versatz der Übereinstimmung innerhalb der Linie. Dies ist die Anzahl der Bytes vom Anfang der Datei bis zum Anfang der Zeile.

text = Die binäre Darstellung der übereinstimmenden Zeile, einschließlich aller <CR> und / oder <LF>. In der Binärausgabe wird nichts ausgelassen, sodass in diesem Beispiel, das mit allen Zeilen übereinstimmt, eine exakte Binärkopie der Originaldatei erstellt wird.

FINDSTR "^" FILE >FILE_COPY

Die Option / A legt die Farbe der Ausgabe von fileName:, lineNumber: und lineOffset: fest. Der Text der übereinstimmenden Zeile wird immer mit der aktuellen Konsolenfarbe ausgegeben. Die Option / A wird nur wirksam, wenn die Ausgabe direkt auf der Konsole angezeigt wird. Die Option / A hat keine Auswirkung, wenn die Ausgabe in eine Datei umgeleitet oder weitergeleitet wird. Siehe die 2018.08.18 bearbeiten in Aacini Antwort für eine Beschreibung des Buggys Verhalten , wenn der Ausgang zu CON umgeleitet wird.

Die meisten Steuerzeichen und viele erweiterte ASCII-Zeichen werden unter XP als Punkte
angezeigt. FINDSTR unter XP zeigt die meisten nicht druckbaren Steuerzeichen aus übereinstimmenden Zeilen als Punkte (Punkte) auf dem Bildschirm an. Die folgenden Steuerzeichen sind Ausnahmen. Sie werden als sie selbst angezeigt: Registerkarte 0x09, LineFeed 0x0A, Registerkarte Vertikal 0x0B, Formularvorschub 0x0C, Wagenrücklauf 0x0D.

XP FINDSTR konvertiert auch eine Reihe erweiterter ASCII-Zeichen in Punkte. Die erweiterten ASCII-Zeichen, die unter XP als Punkte angezeigt werden, entsprechen denen, die bei der Eingabe in der Befehlszeile transformiert werden. Weitere Informationen finden Sie im Abschnitt "Zeichenbeschränkungen für Befehlszeilenparameter - Erweiterte ASCII-Transformation" weiter unten in diesem Beitrag

Steuerzeichen und erweitertes ASCII werden unter XP nicht in Punkte konvertiert, wenn die Ausgabe weitergeleitet, in eine Datei oder in eine FOR IN () -Klausel umgeleitet wird.

Vista und Windows 7 zeigen immer alle Zeichen als sich selbst an, niemals als Punkte.

Rückkehrcodes (ERRORLEVEL)

  • 0 (Erfolg)
    • Übereinstimmung wurde in mindestens einer Zeile von mindestens einer Datei gefunden.
  • 1 (Fehler)
    • In keiner Zeile einer Datei wurde eine Übereinstimmung gefunden.
    • Ungültige Farbe durch /A:xxOption angegeben
  • 2 (Fehler)
    • Inkompatible Optionen /Lund /Rbeide angegeben
    • Fehlendes Argument nach /A:, /F:, /C:, /D:, oder/G:
    • Datei angegeben von /F:fileoder /G:filenicht gefunden
  • 255 (Fehler)

Zu durchsuchende Datenquelle (Aktualisiert basierend auf Tests mit Windows 7)
Findstr kann Daten nur aus einer der folgenden Quellen suchen:

  • Dateinamen, die als Argumente angegeben werden und / oder die /F:fileOption verwenden.

  • stdin über Umleitung findstr "searchString" <file

  • Datenstrom aus einer Pipe type file | findstr "searchString"

Argumente / Optionen haben Vorrang vor der Umleitung, die Vorrang vor weitergeleiteten Daten hat.

Dateinamenargumente und /F:filekönnen kombiniert werden. Es können mehrere Dateinamenargumente verwendet werden. Wenn mehrere /F:fileOptionen angegeben sind, wird nur die letzte verwendet. Platzhalter sind in Dateinamenargumenten zulässig, jedoch nicht in der Datei, auf die von verwiesen wird /F:file.

Quelle der Suchzeichenfolgen (Aktualisiert basierend auf Tests mit Windows 7)
Die Optionen /G:fileund /C:stringkönnen kombiniert werden. Es /C:stringkönnen mehrere Optionen angegeben werden. Wenn mehrere /G:fileOptionen angegeben sind, wird nur die letzte verwendet. Wenn entweder /G:fileoder /C:stringverwendet wird, wird angenommen, dass alle Nichtoptionsargumente zu durchsuchende Dateien sind. Wenn weder /G:filenoch /C:stringverwendet wird, wird das erste Argument ohne Option als durch Leerzeichen getrennte Liste von Suchbegriffen behandelt.

Dateinamen dürfen bei Verwendung der /F:FILEOption nicht in der Datei angegeben werden .
Dateinamen können Leerzeichen und andere Sonderzeichen enthalten. Die meisten Befehle erfordern, dass solche Dateinamen in Anführungszeichen gesetzt werden. Die /F:files.txtOption FINDSTR erfordert jedoch, dass Dateinamen in files.txt NICHT in Anführungszeichen gesetzt werden dürfen. Die Datei wird nicht gefunden, wenn der Name in Anführungszeichen steht.

BUG - Kurze 8.3-Dateinamen können die Optionen /Dund brechen./S
Wie bei allen Windows-Befehlen versucht FINDSTR, bei der Suche nach zu durchsuchenden Dateien sowohl den langen als auch den kurzen 8.3-Namen abzugleichen. Angenommen, der aktuelle Ordner enthält die folgenden nicht leeren Dateien:

b1.txt
b.txt2
c.txt

Der folgende Befehl findet erfolgreich alle 3 Dateien:

findstr /m "^" *.txt

b.txt2stimmt überein, weil der entsprechende Kurzname B9F64~1.TXTübereinstimmt. Dies stimmt mit dem Verhalten aller anderen Windows-Befehle überein.

Ein Fehler mit den Optionen /Dund führt jedoch dazu /S, dass die folgenden Befehle nur gefunden werdenb1.txt

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

Der Fehler verhindert, b.txt2dass alle Dateinamen gefunden werden, nach denen b.txt2im selben Verzeichnis sortiert wird . Zusätzliche Dateien, die zuvor sortiert wurden a.txt, werden gefunden. Zusätzliche Dateien, die später sortiert werden d.txt, werden übersehen, sobald der Fehler ausgelöst wurde.

Jedes durchsuchte Verzeichnis wird unabhängig behandelt. Beispielsweise /Swürde die Option erfolgreich mit der Suche in einem untergeordneten Ordner beginnen, nachdem keine Dateien im übergeordneten Ordner gefunden wurden. Sobald der Fehler jedoch dazu führt, dass ein kurzer Dateiname im untergeordneten Ordner übersehen wird, werden auch alle nachfolgenden Dateien in diesem untergeordneten Ordner übersehen .

Die Befehle funktionieren fehlerfrei, wenn auf einem Computer, auf dem die NTFS 8.3-Namensgenerierung deaktiviert ist, dieselben Dateinamen erstellt werden. Natürlich b.txt2würde nicht gefunden werden, aber c.txtwürde richtig gefunden werden.

Nicht alle Kurznamen lösen den Fehler aus. Alle Fälle von fehlerhaftem Verhalten, die ich gesehen habe, betreffen eine Erweiterung, die länger als 3 Zeichen ist, mit einem kurzen 8.3-Namen, der genauso beginnt wie ein normaler Name, für den kein 8.3-Name erforderlich ist.

Der Fehler wurde unter XP, Vista und Windows 7 bestätigt.

Nicht druckbare Zeichen und die /POption
Mit dieser /POption überspringt FINDSTR alle Dateien, die einen der folgenden Dezimalbyte-Codes enthalten:
0-7, 14-25, 27-31.

Anders ausgedrückt, die /POption überspringt nur Dateien, die nicht druckbare Steuerzeichen enthalten. Steuerzeichen sind Codes kleiner oder gleich 31 (0x1F). FINDSTR behandelt die folgenden Steuerzeichen als druckbar:

 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)

Alle anderen Steuerzeichen werden als nicht druckbar behandelt. Wenn sie vorhanden sind, kann /Pdie Datei übersprungen werden.

Weitergeleitete und umgeleitete Eingabe wurde möglicherweise <CR><LF>angehängt.
Wenn die Eingabe weitergeleitet wird und das letzte Zeichen des Streams nicht angehängt ist <LF>, wird FINDSTR automatisch <CR><LF>an die Eingabe angehängt . Dies wurde unter XP, Vista und Windows 7 bestätigt. (Früher dachte ich, dass die Windows-Pipe für die Änderung der Eingabe verantwortlich ist, aber seitdem habe ich festgestellt, dass FINDSTR die Änderung tatsächlich vornimmt.)

Gleiches gilt für umgeleitete Eingaben unter Vista. Wenn das letzte Zeichen einer Datei, die als umgeleitete Eingabe verwendet wird, nicht ist <LF>, wird FINDSTR automatisch <CR><LF>an die Eingabe angehängt . XP und Windows 7 ändern jedoch keine umgeleiteten Eingaben.

FINDSTR hängt unter XP und Windows 7, wenn die umgeleitete Eingabe nicht mit endet.<LF>
Dies ist eine unangenehme "Funktion" unter XP und Windows 7. Wenn das letzte Zeichen einer Datei, die als umgeleitete Eingabe verwendet wird, nicht mit <LF>endet, bleibt FINDSTR auf unbestimmte Zeit hängen erreicht das Ende der umgeleiteten Datei.

Die letzte Zeile der weitergeleiteten Daten wird möglicherweise ignoriert, wenn sie aus einem einzelnen Zeichen besteht.
Wenn die Eingabe eingespeist wird und die letzte Zeile aus einem einzelnen Zeichen besteht, auf das nicht folgt <LF>, ignoriert FINDSTR die letzte Zeile vollständig.

Beispiel - Der erste Befehl mit einem einzelnen Zeichen und nein <LF>stimmt nicht überein, aber der zweite Befehl mit 2 Zeichen funktioniert einwandfrei, ebenso wie der dritte Befehl, der ein Zeichen mit abschließendem Zeilenumbruch enthält.

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

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

> echo x| findstr "^"
x

Berichtet von DosTips-Benutzer Sponge Belly bei neuem findstr-Fehler . Bestätigt unter XP, Windows 7 und Windows 8. Ich habe noch nichts von Vista gehört. (Ich muss Vista nicht mehr testen).

Optionssyntax
Optionen können entweder vorangestellt werden /oder - Optionen können nach einem einzelnen /oder verkettet werden -. Die verkettete Optionsliste kann jedoch höchstens eine Option mit mehreren Zeichen wie AUS oder F: enthalten, und die Option mit mehreren Zeichen muss die letzte Option in der Liste sein.

Im Folgenden finden Sie alle äquivalenten Möglichkeiten, um eine Regex-Suche ohne Berücksichtigung der Groß- und Kleinschreibung für eine Zeile auszudrücken, die sowohl "Hallo" als auch "Auf Wiedersehen" in beliebiger Reihenfolge enthält

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

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

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

Längenbeschränkungen für Suchzeichenfolgen
Unter Vista beträgt die maximal zulässige Länge für eine einzelne Suchzeichenfolge 511 Byte. Wenn eine FINDSTR: Search string too long.Suchzeichenfolge 511 überschreitet, ist das Ergebnis ein Fehler mit ERRORLEVEL 2.

Bei einer Suche nach regulären Ausdrücken beträgt die maximale Länge der FINDSTR: Out of memorySuchzeichenfolge 254. Ein regulärer Ausdruck mit einer Länge zwischen 255 und 511 führt zu einem Fehler mit ERRORLEVEL 2. Eine Länge eines regulären Ausdrucks> 511 führt zu dem FINDSTR: Search string too long.Fehler.

Unter Windows XP ist die Länge der Suchzeichenfolge anscheinend kürzer. Findstr-Fehler: "Suchzeichenfolge zu lang": Wie wird die Teilzeichenfolge in der "for" -Schleife extrahiert und abgeglichen? Das XP-Limit beträgt 127 Byte für Literal- und Regex-Suchen.

Zeilenlängenbeschränkungen
Dateien, die als Befehlszeilenargument oder über die Option / F: FILE angegeben wurden, haben keine bekannte Zeilenlängenbeschränkung. Die Suche wurde erfolgreich für eine 128-MB-Datei ausgeführt, die kein einziges <LF> enthielt.

Weitergeleitete Daten und umgeleitete Eingaben sind auf 8191 Byte pro Zeile begrenzt. Diese Grenze ist ein "Merkmal" von FINDSTR. Es ist nicht mit Rohren oder Umleitungen verbunden. FINDSTR, das umgeleitete stdin- oder Piped-Eingaben verwendet, stimmt niemals mit einer Zeile überein, die> = 8 KByte ist. Zeilen> = 8k erzeugen eine Fehlermeldung an stderr, aber ERRORLEVEL ist immer noch 0, wenn die Suchzeichenfolge in mindestens einer Zeile von mindestens einer Datei gefunden wird.

Standard-Suchtyp: Literal vs Regular Expression
/C:"string" - Der Standard ist / L Literal. Das explizite Kombinieren der Option / L mit / C: "string" funktioniert zwar, ist aber redundant.

"string argument"- Die Standardeinstellung hängt vom Inhalt der ersten Suchzeichenfolge ab. (Denken Sie daran, dass <Leerzeichen> zum Abgrenzen von Suchzeichenfolgen verwendet wird.) Wenn die erste Suchzeichenfolge ein gültiger regulärer Ausdruck ist, der mindestens ein nicht maskiertes Metazeichen enthält, werden alle Suchzeichenfolgen als reguläre Ausdrücke behandelt. Andernfalls werden alle Suchzeichenfolgen als Literale behandelt. Zum Beispiel "51.4 200"wird als zwei reguläre Ausdrücke behandelt werden , da die erste Zeichenfolge einen nicht entgangen Punkt enthält, während "200 51.4"als zwei Literale behandelt werden , da die erste Saite kein Meta-Zeichen enthält.

/G:file- Die Standardeinstellung hängt vom Inhalt der ersten nicht leeren Zeile in der Datei ab. Wenn die erste Suchzeichenfolge ein gültiger regulärer Ausdruck ist, der mindestens ein nicht maskiertes Metazeichen enthält, werden alle Suchzeichenfolgen als reguläre Ausdrücke behandelt. Andernfalls werden alle Suchzeichenfolgen als Literale behandelt.

Empfehlung - Geben Sie bei Verwendung von oder immer explizit die /LLiteraloption oder die Option für /Rreguläre Ausdrücke an ."string argument"/G:file

BUG - Die Angabe mehrerer Literal-Suchzeichenfolgen kann zu unzuverlässigen Ergebnissen führen

Das folgende einfache FINDSTR-Beispiel findet keine Übereinstimmung, obwohl dies der Fall sein sollte.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Dieser Fehler wurde unter Windows Server 2003, Windows XP, Vista und Windows 7 bestätigt.

Basierend auf Experimenten kann FINDSTR fehlschlagen, wenn alle folgenden Bedingungen erfüllt sind:

  • Bei der Suche werden mehrere Literal-Suchzeichenfolgen verwendet
  • Die Suchzeichenfolgen sind unterschiedlich lang
  • Eine kurze Suchzeichenfolge hat eine gewisse Überlappung mit einer längeren Suchzeichenfolge
  • Bei der Suche wird zwischen Groß- und Kleinschreibung unterschieden (keine /IOption).

Bei jedem Fehler, den ich gesehen habe, ist es immer eine der kürzeren Suchzeichenfolgen, die fehlschlägt.

Weitere Informationen finden Sie unter Warum findet dieses FINDSTR-Beispiel mit mehreren Literal-Suchzeichenfolgen keine Übereinstimmung?

Anführungszeichen und Backslahses in Befehlszeilenargumenten
Hinweis - Die Kommentare von Benutzer MC ND spiegeln die tatsächlich schrecklich komplizierten Regeln für diesen Abschnitt wider. Es gibt 3 verschiedene Analysephasen:

  • Für die erste cmd.exe müssen möglicherweise einige Anführungszeichen als ^ "maskiert werden (eigentlich nichts mit FINDSTR zu tun).
  • Als nächstes verwendet FINDSTR den MS C / C ++ - Argumentparser vor 2008 , der spezielle Regeln für "und \" enthält
  • Nach Abschluss des Argumentparsers behandelt FINDSTR zusätzlich \ gefolgt von einem alphanumerischen Zeichen als Literal, gefolgt von einem nicht alphanumerischen Zeichen als Escapezeichen

Der Rest dieses hervorgehobenen Abschnitts ist nicht 100% korrekt. Es kann als Leitfaden für viele Situationen dienen, aber die oben genannten Regeln sind für ein umfassendes Verständnis erforderlich.

Anführungszeichen innerhalb von Befehlszeilensuchzeichenfolgen maskieren Anführungszeichen innerhalb von Befehlszeilensuchzeichenfolgen
müssen mit einem umgekehrten Schrägstrich wie maskiert werden \". Dies gilt sowohl für Literal- als auch für Regex-Suchzeichenfolgen. Diese Informationen wurden unter XP, Vista und Windows 7 bestätigt.

Hinweis: Das Anführungszeichen muss möglicherweise auch für den CMD.EXE-Parser maskiert werden, dies hat jedoch nichts mit FINDSTR zu tun. Um beispielsweise nach einem einfachen Zitat zu suchen, können Sie Folgendes verwenden:

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

Escape-Backslash in Befehlszeilen-Literal-
Suchzeichenfolgen Backslash in einer Literal-Suchzeichenfolge kann normalerweise als \oder als dargestellt werden \\. Sie sind typischerweise gleichwertig. (In Vista kann es ungewöhnliche Fälle geben, in denen der Backslash immer maskiert werden muss, aber ich habe keinen Vista-Computer mehr zum Testen) .

Es gibt jedoch einige Sonderfälle:

Bei der Suche nach aufeinanderfolgenden Backslashes müssen alle bis auf den letzten maskiert werden. Der letzte Backslash kann optional maskiert werden.

  • \\kann als \\\oder codiert werden\\\\
  • \\\kann als \\\\\oder codiert werden\\\\\\

Die Suche nach einem oder mehreren Backslashes vor einem Zitat ist bizarr. Die Logik würde vorschlagen, dass das Zitat maskiert werden muss und jeder der führenden Backslashes maskiert werden muss, aber das funktioniert nicht! Stattdessen muss jeder der führenden Backslashes doppelt maskiert werden, und das Anführungszeichen wird normalerweise maskiert:

  • \" muss codiert sein als \\\\\"
  • \\" muss codiert sein als \\\\\\\\\"

Wie bereits erwähnt, müssen ^für den CMD-Parser möglicherweise auch ein oder mehrere Escape-Anführungszeichen mit Escapezeichen versehen werden

Die Informationen in diesem Abschnitt wurden unter XP und Windows 7 bestätigt.

Escaping Backslash innerhalb von Regex-Suchzeichenfolgen in der Befehlszeile

  • Nur Vista: Backslash in einem regulären Ausdruck muss entweder doppelt maskiert \\\\oder einfach innerhalb eines Zeichenklassensatzes wie einfach maskiert sein[\\]

  • XP und Windows 7: Backslash in einem regulären Ausdruck kann immer als dargestellt werden [\\]. Es kann normalerweise als dargestellt werden \\. Dies funktioniert jedoch nie, wenn der Backslash vor einem Escape-Zitat steht.

    Ein oder mehrere Backslashes vor einem Escape-Zitat müssen entweder doppelt maskiert oder als codiert sein [\\]

    • \"kann als \\\\\"oder codiert werden[\\]\"
    • \\"kann als \\\\\\\\\"oder [\\][\\]\"oder codiert sein\\[\\]\"

Escape-
Anführungszeichen und Backslash in / G: FILE-Literal-Suchzeichenfolgen Eigenständige Anführungszeichen und Backslashes in einer durch / G: -Datei angegebenen Literal-Suchzeichenfolge müssen nicht maskiert werden, können es aber sein.

"und \"sind gleichwertig.

\und \\sind gleichwertig.

Wenn die Absicht besteht, \\ zu finden, muss mindestens der führende Backslash maskiert werden. Beides \\\und \\\\Arbeit.

Wenn die Absicht besteht, "" zu finden, muss mindestens der führende Backslash maskiert werden. Beides \\"und \\\"funktionieren.

Escape-Anführungszeichen und Backslash in / G: FILE-Regex-Suchzeichenfolgen
Dies ist der einzige Fall, in dem die Escape-Sequenzen gemäß der Dokumentation wie erwartet funktionieren. Quote ist kein Regex-Metazeichen, daher muss es nicht maskiert werden (kann es aber sein). Backslash ist ein Regex-Metazeichen, daher muss es maskiert werden.


Zeichenbeschränkungen für Befehlszeilenparameter - Erweiterte ASCII-Umwandlung Das Nullzeichen (0x00) kann in keiner Zeichenfolge in der Befehlszeile angezeigt werden. Jedes andere Einzelbytezeichen kann in der Zeichenfolge erscheinen (0x01 - 0xFF). FINDSTR konvertiert jedoch viele erweiterte ASCII-Zeichen, die in Befehlszeilenparametern gefunden werden, in andere Zeichen. Dies hat zwei wesentliche Auswirkungen:

1) Viele erweiterte ASCII-Zeichen stimmen nicht überein, wenn sie als Suchzeichenfolge in der Befehlszeile verwendet werden. Diese Einschränkung gilt auch für Literal- und Regex-Suchen. Wenn eine Suchzeichenfolge erweitertes ASCII enthalten muss, /G:FILEsollte stattdessen die Option verwendet werden.

2) FINDSTR kann möglicherweise keine Datei finden, wenn der Name erweiterte ASCII-Zeichen enthält und der Dateiname in der Befehlszeile angegeben ist. Wenn eine zu durchsuchende Datei erweitertes ASCII im Namen enthält, /F:FILEsollte stattdessen die Option verwendet werden.

Hier finden Sie eine vollständige Liste der erweiterten ASCII-Zeichentransformationen, die FINDSTR für Befehlszeilenzeichenfolgen ausführt. Jedes Zeichen wird als Dezimalbytecodewert dargestellt. Der erste Code repräsentiert das Zeichen, wie es in der Befehlszeile angegeben ist, und der zweite Code repräsentiert das Zeichen, in das es transformiert wird. Hinweis - Diese Liste wurde auf einem US-Computer erstellt. Ich weiß nicht, welchen Einfluss andere Sprachen auf diese Liste haben könnten.

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

Jedes Zeichen> 0, das nicht in der obigen Liste enthalten ist, wird als sich selbst behandelt, einschließlich <CR>und < LF>. Der einfachste Weg, ungerade Zeichen wie <CR>und einzuschließen, <LF>besteht darin, sie in eine Umgebungsvariable zu integrieren und eine verzögerte Erweiterung innerhalb des Befehlszeilenarguments zu verwenden.

Zeichenbeschränkungen für Zeichenfolgen, die in Dateien gefunden werden, die durch die Optionen / G: FILE und / F: FILE angegeben sind.
Das Zeichen nul (0x00) kann in der Datei angezeigt werden, funktioniert jedoch wie der C-Zeichenfolgenabschluss. Alle Zeichen nach einem Nullzeichen werden als eine andere Zeichenfolge behandelt, als wären sie in einer anderen Zeile.

Die Zeichen <CR>und <LF>werden als Zeilenabschlusszeichen behandelt, die eine Zeichenfolge beenden, und sind nicht in der Zeichenfolge enthalten.

Alle anderen Einzelbytezeichen sind perfekt in einer Zeichenfolge enthalten.

Durchsuchen von Unicode-Dateien FINDSTR kann die meisten Unicode-Dateien
(UTF-16, UTF-16LE, UTF-16BE, UTF-32) nicht ordnungsgemäß durchsuchen, da es nicht nach Null-Bytes suchen kann und Unicode normalerweise viele Null-Bytes enthält.

Der Befehl TYPE konvertiert jedoch UTF-16LE mit Stückliste in einen Einzelbyte-Zeichensatz, sodass ein Befehl wie der folgende mit UTF-16LE mit Stückliste funktioniert.

type unicode.txt|findstr "search"

Beachten Sie, dass Unicode-Codepunkte, die von Ihrer aktiven Codepage nicht unterstützt werden, in ?Zeichen konvertiert werden .

Es ist möglich, UTF-8 zu durchsuchen, solange Ihre Suchzeichenfolge nur ASCII enthält. Die Konsolenausgabe von Multi-Byte-UTF-8-Zeichen ist jedoch nicht korrekt. Wenn Sie die Ausgabe jedoch in eine Datei umleiten, wird das Ergebnis korrekt in UTF-8 codiert. Beachten Sie, dass wenn die UTF-8-Datei eine Stückliste enthält, die Stückliste als Teil der ersten Zeile betrachtet wird, wodurch eine Suche ausgelöst werden kann, die dem Zeilenanfang entspricht.

Es ist möglich, Multi-Byte-UTF-8-Zeichen zu durchsuchen, wenn Sie Ihre Suchzeichenfolge in eine UTF-8-codierte Suchdatei (ohne Stückliste) einfügen und die Option / G verwenden.

End Of Line
FINDSTR bricht Zeilen unmittelbar nach jedem <LF>. Das Vorhandensein oder Fehlen von <CR> hat keinen Einfluss auf Zeilenumbrüche.

Suchen über Zeilenumbrüche
Wie erwartet .stimmt das Regex-Metazeichen nicht mit <CR> oder <LF> überein. Es ist jedoch möglich, mithilfe einer Befehlszeilensuchzeichenfolge über einen Zeilenumbruch hinweg zu suchen. Sowohl die Zeichen <CR> als auch <LF> müssen explizit übereinstimmen. Wenn eine mehrzeilige Übereinstimmung gefunden wird, wird nur die erste Zeile der Übereinstimmung gedruckt. FINDSTR kehrt dann zur zweiten Zeile in der Quelle zurück und beginnt die Suche erneut - eine Art Feature vom Typ "Vorausschau".

Angenommen, TEXT.TXT enthält diese Inhalte (könnte Unix- oder Windows-Stil sein).

A
A
A
B
A
A

Dann dieses Skript

@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

gibt diese Ergebnisse

1:A
2:A
5:A

Das Durchsuchen von Zeilenumbrüchen mit der Option / G: FILE ist ungenau, da <CR> oder <LF> nur über einen Ausdrucksbereich für Regex-Zeichenklassen abgeglichen werden können, der die EOL-Zeichen enthält.

  • [<TAB>-<0x0B>] stimmt mit <LF> überein, stimmt aber auch mit <TAB> und <0x0B> überein

  • [<0x0C>-!] stimmt mit <CR> überein, aber es stimmt auch mit <0x0C> und überein!

    Hinweis - Die obigen Angaben sind symbolische Darstellungen des Regex-Byte-Streams, da ich die Zeichen nicht grafisch darstellen kann.

Antwort weiter in Teil 2 unten ...

Dbenham
quelle
45
Hervorragende Vollständigkeit. Wenn nur alle Antworten im Internet so wären.
Mike Viens
1
wir haben ein Problem mit gestoßen addpath.batvon Q141344 und findstr, die den Win7 hängenden Problem in Zusammenhang stehen können oben erwähnt. Ich habe einen Chatroom erstellt, um dies für alle Interessierten aufzuspüren
matt wilkie
2
BEARBEITEN - Beschriebene Anzeige von Steuerzeichen als Punkte unter XP. Außerdem wurden Fehler /Sund /DOptionen dokumentiert , die sich aus kurzen 8.3-Dateinamen ergeben.
Dbenham
1
BEARBEITEN - 1) Dateinamen in der durch / F: FILE angegebenen Datei dürfen nicht in Anführungszeichen gesetzt werden. 2) Die Transformation erweiterter ASCII-Zeichen wirkt sich sowohl auf Suchzeichenfolgen als auch auf Dateinamen aus, wenn diese in der Befehlszeile angegeben werden.
Dbenham
1
BEARBEITEN - Fehler hinzugefügt, bei dem die letzte Zeile der weitergeleiteten Eingabe ignoriert wird, wenn sie aus einem einzelnen Zeichen ohne<LF>
dbenham
64

Antwort Fortsetzung von Teil 1 oben - Ich bin auf das Antwortlimit von 30.000 Zeichen gestoßen :-(


Unterstützung für eingeschränkte reguläre Ausdrücke (Regex) Die Unterstützung von FINDSTR für reguläre Ausdrücke ist äußerst begrenzt. Wenn es nicht in der HELP-Dokumentation enthalten ist, wird es nicht unterstützt.

Darüber hinaus werden die unterstützten Regex-Ausdrücke auf eine völlig unstandardisierte Weise implementiert, sodass die Ergebnisse anders ausfallen können, als dies von grep oder perl erwartet wird.

Die Regex-Linienpositionsanker ^ und $
^ stimmen mit dem Beginn des Eingabestreams sowie mit jeder Position unmittelbar nach einem <LF> überein. Da FINDSTR auch Zeilen nach <LF> unterbricht, stimmt ein einfacher regulärer Ausdruck von "^" immer mit allen Zeilen innerhalb einer Datei überein, auch mit einer Binärdatei.

$Entspricht jeder Position unmittelbar vor einem <CR>. Dies bedeutet, dass eine Regex-Suchzeichenfolge, die enthält $, niemals mit Zeilen in einer Textdatei im Unix-Stil übereinstimmt und auch nicht mit der letzten Zeile einer Windows-Textdatei übereinstimmt, wenn die EOL-Markierung von <CR> <LF> fehlt.

Hinweis - Wie bereits erwähnt, wurde möglicherweise eine <CR><LF>an PINDSTR weitergeleitete und umgeleitete Eingabe angehängt, die sich nicht in der Quelle befindet. Dies kann sich natürlich auf eine Regex-Suche auswirken, die verwendet wird $.

Jede Suchzeichenfolge mit Zeichen davor ^oder danach $findet immer keine Übereinstimmung.

Positionsoptionen / B / E / X
Die Positionsoptionen funktionieren genauso wie ^und $, außer dass sie auch für wörtliche Suchzeichenfolgen funktionieren.

/ B funktioniert genauso wie ^am Anfang einer Regex-Suchzeichenfolge.

/ E funktioniert genauso wie $am Ende einer Regex-Suchzeichenfolge.

/ X funktioniert genauso wie ^am Anfang und $am Ende einer Regex-Suchzeichenfolge.

Die Regex-Wortgrenze
\< muss der allererste Term im Regex sein. Die Regex stimmt mit nichts überein, wenn andere Zeichen davor stehen. \<entspricht entweder dem Anfang der Eingabe, dem Anfang einer Zeile (die Position unmittelbar nach einem <LF>) oder der Position unmittelbar nach einem "Nicht-Wort" -Zeichen. Das nächste Zeichen muss kein "Wort" -Zeichen sein.

\>muss der allerletzte Begriff in der Regex sein. Die Regex stimmt mit nichts überein, wenn andere Zeichen darauf folgen. \>entspricht entweder dem Ende der Eingabe, der Position unmittelbar vor einem <CR> oder der Position unmittelbar vor einem "Nicht-Wort" -Zeichen. Das vorhergehende Zeichen muss kein "Wort" -Zeichen sein.

Hier ist eine vollständige Liste von "Nicht-Wort" -Zeichen, die als Dezimalbytecode dargestellt werden. Hinweis - Diese Liste wurde auf einem US-Computer erstellt. Ich weiß nicht, welchen Einfluss andere Sprachen auf diese Liste haben könnten.

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-Zeichenklassenbereiche [xy]
Zeichenklassenbereiche funktionieren nicht wie erwartet. Siehe diese Frage: Warum behandelt findstr den Fall (unter bestimmten Umständen) nicht richtig? , zusammen mit dieser Antwort: https://stackoverflow.com/a/8767815/1012053 .

Das Problem ist, dass FINDSTR die Zeichen nicht nach ihrem Bytecodewert sortiert (üblicherweise als ASCII-Code gedacht, aber ASCII wird nur von 0x00 - 0x7F definiert). Die meisten Regex-Implementierungen würden [AZ] als alle englischen Großbuchstaben in Großbuchstaben behandeln. FINDSTR verwendet jedoch eine Sortierfolge, die in etwa der Funktionsweise von SORT entspricht. [AZ] enthält also das vollständige englische Alphabet, sowohl in Groß- als auch in Kleinbuchstaben (mit Ausnahme von "a"), sowie nicht-englische Alpha-Zeichen mit diakritischen Zeichen.

Unten finden Sie eine vollständige Liste aller von FINDSTR unterstützten Zeichen, sortiert nach der von FINDSTR zum Festlegen von Regex-Zeichenklassenbereichen verwendeten Sortierfolge. Die Zeichen werden als ihr Dezimalbytecodewert dargestellt. Ich glaube, die Sortierfolge ist am sinnvollsten, wenn die Zeichen mit Codepage 437 angezeigt werden. Hinweis - Diese Liste wurde auf einem US-Computer erstellt. Ich weiß nicht, welchen Einfluss andere Sprachen auf diese Liste haben könnten.

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-Zeichenklassenbegriffsbegrenzung und BUG
FINDSTR ist nicht nur auf maximal 15 Zeichenklassenbegriffe innerhalb eines Regex beschränkt, sondern behandelt auch den Versuch, das Grenzwert zu überschreiten, nicht ordnungsgemäß. Die Verwendung von 16 oder mehr Zeichenklassenbegriffen führt zu einem interaktiven Windows-Popup mit der Meldung "Das Dienstprogramm zum Suchen von Zeichenfolgen (QGREP) ist auf ein Problem gestoßen und muss geschlossen werden. Wir entschuldigen uns für die Unannehmlichkeiten." Der Nachrichtentext variiert je nach Windows-Version geringfügig. Hier ist ein Beispiel für einen FINDSTR, der fehlschlägt:

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]

Dieser Fehler wurde vom DosTips-Benutzer Judago hier gemeldet . Es wurde unter XP, Vista und Windows 7 bestätigt.

Regex-Suchen schlagen fehl (und können unbegrenzt hängen bleiben), wenn sie den Bytecode 0xFF (dezimal 255) enthalten.
Jede Regex-Suche, die den Bytecode 0xFF (dezimal 255) enthält, schlägt fehl. Es schlägt fehl, wenn der Bytecode 0xFF direkt enthalten ist oder implizit in einem Zeichenklassenbereich enthalten ist. Beachten Sie, dass in FINDSTR-Zeichenklassenbereichen keine Zeichen basierend auf dem Bytecodewert sortiert werden. Das Zeichen <0xFF>erscheint relativ früh in der Kollatierungssequenz zwischen den Zeichen <space>und <tab>. Jeder Zeichenklassenbereich, der beides enthält <space>und <tab>fehlschlägt.

Das genaue Verhalten ändert sich je nach Windows-Version geringfügig. Windows 7 bleibt auf unbestimmte Zeit hängen, wenn 0xFF enthalten ist. XP hängt nicht, findet jedoch immer keine Übereinstimmung und gibt gelegentlich die folgende Fehlermeldung aus: "Der Prozess hat versucht, in eine nicht vorhandene Pipe zu schreiben."

Ich habe keinen Zugriff mehr auf einen Vista-Computer, daher konnte ich unter Vista nicht testen.

Regex-Fehler: .und [^anySet]kann mit dem Dateiende übereinstimmen
Das Regex .- Metazeichen sollte nur mit einem anderen Zeichen als <CR>oder übereinstimmen <LF>. Es gibt einen Fehler, der es ermöglicht, mit dem Dateiende übereinzustimmen, wenn die letzte Zeile in der Datei nicht durch beendet wird<CR> oder<LF> . Das .passt jedoch nicht zu einer leeren Datei.

Zum Beispiel eine Datei mit dem Namen "test.txt", die eine einzelne Zeile von enthält x, ohne <CR>oder zu beenden<LF> , mit der folgenden :

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

Dieser Fehler wurde unter XP und Win7 bestätigt.

Gleiches scheint für negative Zeichensätze zu gelten. So etwas passt zum [^abc]Dateiende. Positive Zeichensätze [abc]scheinen gut zu funktionieren. Ich habe dies nur auf Win7 getestet.

Dbenham
quelle
1
findstr ist auch fehlerhaft im Umgang mit großen Dateien. Dateien> 2 GB können dazu führen, dass findstr hängen bleibt. Das passiert nicht immer. Bei der Bestätigung des Fehlers habe ich eine Datei mit 2,3 GB durchsucht, die nicht hängen blieb. Es hängt auch dann, wenn nur eine einzelne Datei durchsucht wird. Umgehung besteht darin, die Ausgabe von typein zu leitenfindstr .
Desillusioniert
Es lohnt sich wahrscheinlich auch ausdrücklich zu erwähnen, dass findstrmehrere Suchzeichenfolgen unterstützt werden /c:. Ich weiß, dass Ihre Antworten dies zeigen. Aber es ist etwas, das nicht dokumentiert ist; und ich war ziemlich überrascht, von der Funktion zu erfahren, nachdem ich findstrsie einige Jahre lang ohne sie verwendet hatte.
Desillusioniert
@CraigYoung - Sie haben Recht mit den Suchzeichenfolgenquellen. Ich habe meine Antwort bearbeitet, danke.
Dbenham
1
Bei weiteren Untersuchungen sieht es nach einer Variation des von LFIhnen dokumentierten Problems aus. Ich habe festgestellt, dass meine Testdatei nicht beendet wurde, LFweil ich sie copyim Anhänge-Modus erstellt habe. Ich habe eine Befehlszeilensitzung eingefügt , um das Problem in einer Antwort zu demonstrieren ( stackoverflow.com/a/22943056/224704 ). Beachten Sie, dass die Eingabe nicht umgeleitet wird und die Suche dennoch hängt. Der exakt gleiche Suchbefehl hängt nicht mit kleineren Dateien zusammen, die ebenfalls nicht enden LF.
Desillusioniert
1
Neuer Befund (Win7): findstr /R /C:"^[0-9][0-9]* [0-3][0-9][0-9]-[0-9][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9]* [0-9]*\.[0-9]*"(15 Zeichenklassen) - ErrorLevel = -1073740791 (0xC0000409), Fehlerdialogfenster : Find String (QGREP) Utility has stopped working; Nach dem Entfernen einer Klasse oder zwei Meta-Zeichen ( *\.) funktioniert es ...
aschipfl
7

findstr hängt manchmal unerwartet beim Durchsuchen großer Dateien.

Ich habe die genauen Bedingungen oder Grenzgrößen nicht bestätigt. Ich vermute, dass jede Datei mit mehr als 2 GB gefährdet ist.

Ich habe gemischte Erfahrungen damit gemacht, es ist also mehr als nur Dateigröße. Dies scheint eine Variation von FINDSTR zu sein, die unter XP und Windows 7 hängt, wenn die umgeleitete Eingabe nicht mit LF endet. Wie gezeigt, tritt dieses spezielle Problem jedoch auf, wenn die Eingabe nicht erfolgt umgeleitet wird.

Die folgende Befehlszeilensitzung (Windows 7) zeigt, wie findstrbeim Durchsuchen einer 3-GB-Datei hängen bleiben kann.

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>

Beachten Sie, dass ich in einem Hex-Editor überprüft habe, dass alle Zeilen mit abgeschlossen sind CRLF. Die einzige Anomalie ist , dass die Datei mit beendet wird 0x1Aaufgrund der Art und Weise copyfunktioniert . Beachten Sie jedoch, dass diese Anomalie bei "kleinen" Dateien kein Problem verursacht .

Mit zusätzlichen Tests habe ich Folgendes bestätigt:

  • Die Verwendung copymit der /bOption für Binärdateien verhindert das Hinzufügen des 0x1AZeichens und findstrhängt nicht an der 3-GB-Datei.
  • Wenn Sie die 3-GB-Datei mit einem anderen Zeichen beenden, bleibt auch ein findstrhängen.
  • Das 0x1A Charakter verursacht keine Probleme in einer "kleinen" Datei. (Ähnliches gilt für andere abschließende Zeichen.)
  • Durch Hinzufügen CRLFnach wird 0x1Adas Problem behoben. ( LFallein würde wahrscheinlich ausreichen.)
  • Verwenden Sie, typeum die Datei in findstrWerke zu leiten, ohne zu hängen. (Dies kann auf einen Nebeneffekt von entweder zurückzuführen sein typeoder |ein zusätzliches Zeilenende einfügen.)
  • Die Verwendung umgeleiteter Eingaben führt <auch findstrzum Hängenbleiben. Dies wird aber erwartet; wie in dbenhams post erklärt : "umgeleitete eingaben müssen mit enden LF" .
Desillusioniert
quelle
1
+1, ich kann das Problem auf meinem Win7-Computer bestätigen. Eine Datei mit einer Größe von genau 2 GB hing, als das letzte Zeichen nicht vorhanden war <LF>. Eine zwei Byte kleinere Datei hing nicht. Sehr böse!
Dbenham
6

Wenn mehrere Befehle in Klammern stehen und Dateien in den gesamten Block umgeleitet werden:

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

... dann bleiben die Dateien geöffnet, solange die Befehle im Block aktiv sind, sodass die Befehle den Dateizeiger der umgeleiteten Dateien verschieben können. Sowohl der Befehl MORE als auch der Befehl FIND verschieben den Stdin-Dateizeiger vor der Verarbeitung an den Anfang der Datei, sodass dieselbe Datei innerhalb des Blocks möglicherweise mehrmals verarbeitet wird. Zum Beispiel dieser Code:

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

... das gleiche Ergebnis erzielen wie dieses:

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

Dieser Code:

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

... das gleiche Ergebnis erzielen wie dieses:

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

FINDSTR ist anders; es ist nicht die Stdin Dateizeiger von seiner aktuellen Position bewegen. Mit diesem Code wird beispielsweise eine neue Zeile nach einer Suchzeile eingefügt:

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

Wir können diese Funktion mit Hilfe eines Hilfsprogramms nutzen, mit dem wir den Dateizeiger einer umgeleiteten Datei verschieben können, wie in diesem Beispiel gezeigt .

Dieses Verhalten wurde zuerst von jeb in diesem Beitrag gemeldet .


EDIT 2018-08-18 : Neuer FINDSTR-Fehler gemeldet

Der Befehl FINDSTR weist einen seltsamen Fehler auf, der auftritt, wenn dieser Befehl zum Anzeigen von Zeichen in Farbe verwendet wird UND die Ausgabe eines solchen Befehls an das CON-Gerät umgeleitet wird. Ausführliche Informationen zur Verwendung des Befehls FINDSTR zum Anzeigen von Text in Farbe finden Sie in diesem Thema .

Wenn die Ausgabe dieser Form des FINDSTR-Befehls an CON umgeleitet wird, passiert etwas Seltsames, nachdem der Text in der gewünschten Farbe ausgegeben wurde: Der gesamte Text nach der Ausgabe als "unsichtbare" Zeichen, obwohl eine genauere Beschreibung lautet, dass der Text ist Ausgabe als schwarzer Text über schwarzem Hintergrund. Der Originaltext wird angezeigt, wenn Sie mit dem Befehl COLOR die Vordergrund- und Hintergrundfarben des gesamten Bildschirms zurücksetzen. Wenn der Text jedoch "unsichtbar" ist, können wir einen SET / P-Befehl ausführen, sodass nicht alle eingegebenen Zeichen auf dem Bildschirm angezeigt werden. Dieses Verhalten kann zur Eingabe von Passwörtern verwendet werden.

@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%"
Aacini
quelle
2

Ich möchte einen Fehler in Bezug auf den Abschnitt Datenquelle melden , nach der in der ersten Antwort gesucht werden soll , wenn en dash (-) oder em dash (-) im Dateinamen verwendet werden.

Wenn Sie die erste Option verwenden möchten - Dateinamen, die als Argumente angegeben werden , wird die Datei nicht gefunden. Sobald Sie entweder Option 2 - Standard über Umleitung oder 3 - Datenstrom aus einer Pipe verwenden , findet findstr die Datei.

Zum Beispiel dieses einfache Batch-Skript:

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

wird drucken:

Dateiname mit en dash:

  1. Als Argument
    FINDSTR: Dateiname kann nicht mit - dash.txt geöffnet werden

  2. Als Standard über Umleitung
    bin ich die Datei mit einem Bindestrich.

  3. Als Datenstrom aus einer Pipe
    bin ich die Datei mit einem Bindestrich.

Dateiname mit Bindestrich:

  1. Als Argument
    FINDSTR: Dateiname kann nicht mit - dash.txt geöffnet werden

  2. Als Standard über Umleitung
    bin ich die Datei mit einem em-Strich.

  3. Als Datenstrom aus einer Pipe
    bin ich die Datei mit einem em-Strich.

Ich hoffe es hilft.

M.

matro
quelle
1
Hallo Matro, obwohl Ihre Kommentare korrekt sein mögen, bin ich mir nicht sicher, ob sie die eigentliche Frage nicht beantworten.
Wai Ha Lee
Ich glaube, dies ist ein Unicode-Problem, das FINDSTR nicht unterstützt. Die CMD.EXE-Umleitung kann einen Dateinamen mit Unicode ordnungsgemäß öffnen, ebenso wie der Befehl TYPE. Aber irgendwo auf der Linie konvertiert FINDSTR sowohl den Bindestrich als auch den Bindestrich in einen normalen Bindestrich, und natürlich kann das Betriebssystem diesen Namen nicht finden. Wenn Sie eine andere Datei erstellen, die den Bindestrich und / oder den Bindestrich durch einen Bindestrich ersetzt, durchsucht FINDSTR die Bindestrichdatei, wenn ein Name mit einem Bindestrich oder einem Bindestrich angegeben ist.
Dbenham
Ich würde dieses Problem eher als Einschränkung als als Fehler klassifizieren.
Dbenham
Eigentlich ist dies weniger ein Unicode-Problem als vielmehr ein erweitertes ASCII-Problem. Ich habe dieses Problem bereits in meiner ursprünglichen Antwort unter der Überschrift Zeichenbeschränkungen für Befehlszeilenparameter - Erweiterte ASCII-Transformation dokumentiert . FINDSTR wandelt eine Reihe erweiterter ASCII-Codes in "verwandte" echte ASCII-Codes um, einschließlich En-Dash und Em-Dash.
Dbenham
1

Das findstr Befehl setzt den ErrorLevel(oder Exit-Code) auf einen der folgenden Werte, da keine ungültigen oder inkompatiblen Schalter vorhanden sind und keine Suchzeichenfolge die geltende Längenbeschränkung überschreitet:

  • 0 wenn in allen angegebenen Dateien mindestens eine einzige Übereinstimmung in einer Zeile gefunden wird;
  • 1 Andernfalls;

Eine Zeile enthält eine Übereinstimmung, wenn:

  • Es wird keine /VOption angegeben und der Suchausdruck kommt mindestens einmal vor.
  • das /V Option ist angegeben und der Suchausdruck wird nicht angezeigt.

Dies bedeutet, dass die /VOption auch die zurückgegebenen ändertErrorLevel , diese jedoch nicht einfach zurücksetzt!

Wenn Sie beispielsweise eine Datei test.txtmit zwei Zeilen haben, von denen eine die Zeichenfolge enthält text, die andere jedoch nicht, beide findstr "text" "test.txt"undfindstr /V "text" "test.txt" eine ErrorLevelvon zurückgeben 0.

Grundsätzlich kann man sagen: Wenn findstrmindestens eine Zeile zurückgegeben wird, ErrorLevelwird auf gesetzt 0, sonst auf 1.

Beachten Sie, dass die /MOption den ErrorLevelWert nicht beeinflusst , sondern nur die Ausgabe ändert.

(Nur der Vollständigkeit halber: Der findBefehl verhält sich in Bezug auf die /VOption genauso und ErrorLeveldie /COption hat keinen Einfluss ErrorLevel.)

aschipfl
quelle
1

FINDSTR hat einen Farbfehler, den ich unter /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to beschrieben und behoben habe -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Um diesen Thread zusammenzufassen: Der Fehler besteht darin, dass Inline-ANSI-Escape-Farbcodes in später ausgeführten Befehlen nicht mehr funktionieren, wenn die Eingabe innerhalb eines in Klammern gesetzten Codeblocks an FINDSTR weitergeleitet wird. Ein Beispiel für Inline-Farbcodes ist:echo %magenta%Alert: Something bad happened%yellow% (wobei Magenta und Gelb sind, die zuvor in der .bat-Datei als entsprechende ANSI-Escape-Farbcodes definiert wurden).

Meine anfängliche Lösung bestand darin, nach dem FINDSTR eine Nicht-Unterroutine aufzurufen. Irgendwie "setzt" der Anruf oder die Rückgabe alles zurück, was zurückgesetzt werden muss.

Später entdeckte ich eine andere Lösung, die vermutlich effizienter ist: Platzieren Sie die FINDSTR-Phrase in Klammern, wie im folgenden Beispiel: echo success | ( FINDSTR /R success ) Das Platzieren der FINDSTR-Phrase in einem verschachtelten Codeblock scheint den Farbcode-Fehler von FINDSTR zu isolieren, sodass er keinen Einfluss darauf hat, was sich außerhalb der verschachtelten befindet Block. Vielleicht löst diese Technik auch einige andere unerwünschte FINDSTR-Nebenwirkungen .

Dolores Stevens
quelle
Toller Fund. Ihre Regeln können jedoch vereinfacht werden (zumindest auf meinem Windows 10-Unternehmenscomputer). FINDSTR verhindert, dass alle Konsolen-Escape-Sequenzen für nachfolgende Befehle innerhalb desselben Befehlsblocks funktionieren. Es spielt keine Rolle, ob FINDSTR eine Pipe, eine umgeleitete Eingabe oder eine Datei liest. Der Escape-Sequenzfehler ist nicht auf Farbcodes beschränkt. Ein Befehlsblock ist ein beliebiger Satz von Befehlen in Klammern und / oder Befehlen, die über &, && oder || verkettet sind
Dbenham
@dbenham: Schöne Verallgemeinerung des Problems. Wissen Sie, ob meine Lösung - das Verschachteln der FINDSTR-Phrase in Klammern - auch im allgemeinen Fall funktioniert? Und wissen Sie, ob meine Lösung unerwünschte Nebenwirkungen hat?
Dolores Stevens
Ich habe keine erschöpfenden Tests durchgeführt, aber ja, die verschachtelten Klammern scheinen eine allgemeine Lösung zu sein, und ich kann mir keine möglichen unerwünschten Nebenwirkungen vorstellen.
Dbenham
-1

/ D Tipp für mehrere Verzeichnisse: Stellen Sie Ihre Verzeichnisliste vor die Suchzeichenfolge. Diese alle funktionieren:

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

Wie erwartet ist der Pfad relativ zum Speicherort, wenn Sie die Verzeichnisse nicht mit starten \. Das Umgeben des Pfads mit "ist optional, wenn die Verzeichnisnamen keine Leerzeichen enthalten. Das Ende \ist optional. Die Ausgabe des Standorts enthält den von Ihnen angegebenen Pfad. Es funktioniert mit oder ohne Umgeben der Verzeichnisliste mit ".

Gordon
quelle
Ich sehe hier nichts undokumentiertes. Die Option / D wird in der integrierten Hilfe beschrieben. Dies ist keine Frage für allgemeine Tipps zur Verwendung von FINDSTR. Es ist strengstens beabsichtigt, undokumentierte Funktionen, Einschränkungen und / oder Fehler aufzulisten.
Dbenham
1
@dbenham stimmt, es ist nicht wirklich undokumentiert, aber ich stellte fest, dass ich mit findstr arbeiten musste, um die gewünschten Ergebnisse zu erzielen, und teile mit, was ich als DID-Arbeit empfunden habe, damit die Leute keine Zeit damit verschwenden, mit Befehlen zu experimentieren, die NICHT funktionieren. hth (Ich bin traurig, dass Sie meine Eingabe nicht mögen - sie sollte nur konstruktiv sein)
Gordon
IMHO ist der / D-Schalter in der eingebauten Hilfe klar beschrieben: /D:dirlist Search a semicolon-delimited list of directoriesund er steht vor der Suchzeichenfolge, so dass ich nicht verstehe, was genau "Sie" über den / D-Schalter gefunden haben (und was sind die "Befehle, die" NICHT arbeiten ") ...
Aacini
@Aacini in vielen Sprachen spielt die Reihenfolge der Attribute keine Rolle. Ich verstehe zuerst die Dokumentation für findstrListen / D. Ja, ich habe kein Argument dafür, dass das Feature dokumentiert wird. Es ist nur nicht dokumentiert, dass die Reihenfolge der Attribute von Bedeutung ist. Ich mache sehr wenig Kommandozeilenarbeit. Als ich also einen Befehl gepflastert habe und nicht wusste, dass die Reihenfolge einen Unterschied macht, habe ich nur die Attribute hinzugefügt, als ich zu ihnen kam (und alphabetisch steht C vor D). Ich war sehr frustriert und habe meine "gefundenen" Erfahrungen für alle anderen geteilt, die nicht viel mit der Kommandozeile arbeiten.
Gordon
1
Die Reihenfolge der optionalen Attribute spielt normalerweise keine Rolle. In der findstrDokumentation wird angegeben, dass das stringsTeil NICHT optional ist und dass Sie es nach den optionalen Attributen und vor der Liste der optionalen Dateinamen platzieren müssen. Wenn "Ihr gefunden" darin besteht, dass die Verwendung eines Befehls ohne Befolgung seines Verwendungsformats einen Fehler verursacht, ist ein solcher Punkt gut dokumentiert. Siehe Befehlssyntax : "Die Syntax wird in der Reihenfolge angezeigt, in der Sie einen Befehl und alle darauf folgenden Parameter
eingeben müssen