Quali sono le funzionalità e le limitazioni non documentate del comando FINDSTR di Windows?

StackOverflow https://stackoverflow.com/questions/8844868

  •  27-10-2019
  •  | 
  •  

Domanda

Il comando FINDSTR di Windows è orribilmente documentato.È disponibile una guida di base della riga di comando FINDSTR /?, O HELP FINDSTR, ma è deplorevolmente inadeguato.C'è un po' più di documentazione online su https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr.

Esistono molte funzionalità e limitazioni di FINDSTR che non sono nemmeno accennate nella documentazione.Né potrebbero essere previsti senza una conoscenza preliminare e/o un’attenta sperimentazione.

Quindi la domanda è: Quali sono le funzionalità e le limitazioni di FINDSTR non documentate?

Lo scopo di questa domanda è fornire un archivio unico delle numerose funzionalità non documentate in modo che:

R) Gli sviluppatori possono sfruttare appieno le funzionalità disponibili.

B) Gli sviluppatori non perdono tempo a chiedersi perché qualcosa non funziona quando sembra che dovrebbe.

Assicurati di conoscere la documentazione esistente prima di rispondere.Se le informazioni sono coperte da HELP, non appartengono a questo posto.

Né questo è un luogo per mostrare usi interessanti di FINDSTR.Se una persona logica potesse anticipare il comportamento di un particolare utilizzo di FINDSTR sulla base della documentazione, allora non dovrebbe essere qui.

Allo stesso modo, se una persona logica potesse anticipare il comportamento di un particolare utilizzo sulla base delle informazioni contenute in qualsiasi risposta esistente, allora, ancora una volta, ciò non dovrebbe essere qui.

È stato utile?

Soluzione

Prefazione
Gran parte delle informazioni contenute in questa risposta sono state raccolte sulla base di esperimenti eseguiti su una macchina Vista.Salvo diversa indicazione esplicita, non ho confermato se le informazioni si applicano ad altre versioni di Windows.

Uscita TROVASTR
La documentazione non si preoccupa mai di spiegare l'output di FINDSTR.Allude al fatto che vengono stampate le linee corrispondenti, ma niente di più.

Il formato dell'output della riga corrispondente è il seguente:

nomefile:numerolinea:lineOffset:testo

Dove

nome del file: = Il nome del file contenente la riga corrispondente.Il nome del file non viene stampato se la richiesta era esplicitamente per un singolo file o se si cerca input convogliato o input reindirizzato.Una volta stampato, fileName includerà sempre tutte le informazioni sul percorso fornite.Ulteriori informazioni sul percorso verranno aggiunte se il file /S viene utilizzata l'opzione.Il percorso stampato è sempre relativo al percorso fornito o relativo alla directory corrente se non ne viene fornita alcuna.

Nota: è possibile evitare il prefisso del nome file durante la ricerca di più file utilizzando l'estensione caratteri jolly non standard (e scarsamente documentati). < E >.È possibile trovare le regole esatte su come funzionano questi caratteri jolly Qui.Finalmente puoi guardare questo esempio di come funzionano i caratteri jolly non standard con FINDSTR.

numerolinea: = Il numero di riga della riga corrispondente rappresentato come valore decimale con 1 che rappresenta la prima riga dell'input.Stampato solo se /N l'opzione è specificata.

offsetlinea: = L'offset in byte decimali dell'inizio della riga corrispondente, dove 0 rappresenta il primo carattere della prima riga.Stampato solo se /O l'opzione è specificata.Questo è non l'offset della corrispondenza all'interno della linea.È il numero di byte dall'inizio del file all'inizio della riga.

testo = La rappresentazione binaria della linea corrispondente, incluso qualsiasi <CR> e/o <LF>.Nulla viene lasciato fuori dall'output binario, in modo tale che questo esempio che corrisponde a tutte le righe produrrà una copia binaria esatta del file originale.

FINDSTR "^" FILE >FILE_COPY

La maggior parte dei caratteri di controllo e molti caratteri ASCII estesi vengono visualizzati come punti su XP
FINDSTR su XP visualizza la maggior parte dei caratteri di controllo non stampabili dalle linee corrispondenti come punti (punti) sullo schermo.I seguenti caratteri di controllo sono eccezioni;vengono visualizzati come se stessi:Scheda 0x09, avanzamento riga 0x0A, scheda verticale 0x0B, avanzamento modulo 0x0C, ritorno a capo 0x0D.

XP FINDSTR converte anche un numero di caratteri ASCII estesi in punti.I caratteri ASCII estesi visualizzati come punti su XP sono gli stessi che vengono trasformati quando forniti sulla riga di comando.Vedi il "Limiti di caratteri per i parametri della riga di comando - Trasformazione ASCII estesa" sezione, più avanti in questo post

I caratteri di controllo e l'ASCII esteso non vengono convertiti in punti su XP se l'output viene inviato tramite pipe, reindirizzato a un file o all'interno di una clausola FOR IN().

Vista e Windows 7 visualizzano sempre tutti i caratteri come se stessi, mai come punti.

Codici di ritorno (ERRORLEVEL)

  • 0 (successo)
    • È stata trovata una corrispondenza in almeno una riga di almeno un file.
  • 1 (fallimento)
    • Non è stata trovata alcuna corrispondenza in nessuna riga di nessun file.
    • Colore non valido specificato da /A:xx opzione
  • 2 (errore)
    • Opzioni incompatibili /L E /R entrambi specificati
    • Argomento mancante dopo /A:, /F:, /C:, /D:, O /G:
    • File specificato da /F:file O /G:file non trovato
  • 255 (errore)

Origine dei dati da cercare (Aggiornato in base ai test con Windows 7)
Findstr può cercare dati solo da una delle seguenti origini:

  • nomi di file specificati come argomenti e/o utilizzando l'estensione /F:file opzione.

  • stdin tramite reindirizzamento findstr "searchString" <file

  • flusso di dati da una pipe type file | findstr "searchString"

Gli argomenti/opzioni hanno la precedenza sul reindirizzamento, che a sua volta ha la precedenza sui dati trasmessi.

Argomenti del nome file e /F:file possono essere combinati.È possibile utilizzare più argomenti per i nomi dei file.Se multipli /F:file vengono specificate le opzioni, verrà utilizzata solo l'ultima.I caratteri jolly sono consentiti negli argomenti dei nomi file, ma non all'interno del file a cui punta /F:file.

Origine delle stringhe di ricerca (Aggiornato in base ai test con Windows 7)
IL /G:file E /C:string le opzioni possono essere combinate.Molteplici /C:string è possibile specificare le opzioni.Se multipli /G:file vengono specificate le opzioni, verrà utilizzata solo l'ultima.Se l'uno o l'altro /G:file O /C:string viene utilizzato, si presuppone che tutti gli argomenti non opzionali siano file da cercare.Se nessuno dei due /G:file/C:string viene utilizzato, il primo argomento non opzionale viene trattato come un elenco di termini di ricerca delimitato da spazi.

I nomi dei file non devono essere citati all'interno del file quando si utilizza l'estensione /F:FILE opzione.
I nomi dei file possono contenere spazi e altri caratteri speciali.La maggior parte dei comandi richiedono che tali nomi di file siano citati.Ma il FINDSTR /F:files.txt l'opzione richiede che i nomi dei file all'interno di files.txt NON debbano essere racchiusi tra virgolette.Il file non verrà trovato se il nome è citato.

BUG: i nomi di file 8.3 brevi possono interrompere il file /D E /S opzioni
Come con tutti i comandi di Windows, FINDSTR tenterà di abbinare sia il nome lungo che il nome breve 8.3 durante la ricerca dei file da cercare.Supponiamo che la cartella corrente contenga i seguenti file non vuoti:

b1.txt
b.txt2
c.txt

Il seguente comando troverà correttamente tutti e 3 i file:

findstr /m "^" *.txt

b.txt2 corrisponde perché il nome breve corrispondente B9F64~1.TXT partite.Ciò è coerente con il comportamento di tutti gli altri comandi di Windows.

Ma un bug con il /D E /S options fa sì che i seguenti comandi trovino solo b1.txt

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

Il bug impedisce b.txt2 dall'essere trovati, così come tutti i nomi di file ordinati dopo b.txt2 all'interno della stessa directory.File aggiuntivi che vengono ordinati prima, come a.txt, vengono trovati.File aggiuntivi che vengono ordinati in seguito, come d.txt, vengono persi una volta che il bug è stato attivato.

Ogni directory cercata viene trattata in modo indipendente.Ad esempio, il /S l'opzione inizierà con successo la ricerca in una cartella secondaria dopo aver fallito nel trovare i file nella cartella principale, ma una volta che il bug fa sì che un nome file breve venga mancato nella cartella secondaria, verranno persi anche tutti i file successivi in ​​quella cartella secondaria.

I comandi funzionano senza errori se gli stessi nomi di file vengono creati su un computer in cui la generazione dei nomi NTFS 8.3 è disabilitata.Ovviamente b.txt2 non sarebbe stato trovato, ma c.txt verrebbe trovato correttamente.

Non tutti i nomi brevi attivano il bug.Tutti i casi di comportamento disturbato che ho riscontrato coinvolgono un'estensione più lunga di 3 caratteri con un nome breve 8.3 che inizia come un nome normale che non richiede un nome 8.3.

Il bug è stato confermato su XP, Vista e Windows 7.

Caratteri non stampabili e i /P opzione
IL /P l'opzione fa sì che FINDSTR salti qualsiasi file che contenga uno dei seguenti codici byte decimali:
0-7, 14-25, 27-31.

Detto in altro modo, il /P L'opzione salterà solo i file che contengono caratteri di controllo non stampabili.I caratteri di controllo sono codici inferiori o uguali a 31 (0x1F).FINDSTR considera stampabili i seguenti caratteri di controllo:

 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)

Tutti gli altri caratteri di controllo vengono trattati come non stampabili, la cui presenza causa il file /P opzione per saltare il file.

Potrebbero essere presenti input convogliati e reindirizzati <CR><LF> aggiunto
Se l'input viene collegato tramite pipe e l'ultimo carattere del flusso non lo è <LF>, FINDSTR verrà aggiunto automaticamente <CR><LF> all'ingresso.Ciò è stato confermato su XP, Vista e Windows 7. (Pensavo che la pipe di Windows fosse responsabile della modifica dell'input, ma da allora ho scoperto che FINDSTR sta effettivamente eseguendo la modifica.)

Lo stesso vale per l'input reindirizzato su Vista.Se l'ultimo carattere di un file utilizzato come input reindirizzato non lo è <LF>, FINDSTR verrà aggiunto automaticamente <CR><LF> all'ingresso.Tuttavia, XP e Windows 7 non alterano l'input reindirizzato.

FINDSTR si blocca su XP e Windows 7 se l'input reindirizzato non termina con <LF>
Questa è una brutta "funzionalità" su XP e Windows 7.Se l'ultimo carattere di un file utilizzato come input reindirizzato non termina con <LF>, FINDSTR si bloccherà per un tempo indefinito una volta raggiunta la fine del file reindirizzato.

L'ultima riga di dati reindirizzati può essere ignorata se è costituita da un singolo carattere
Se l'input viene collegato tramite pipe e l'ultima riga è costituita da un singolo carattere non seguito da <LF>, FINDSTR ignora completamente l'ultima riga.

Esempio - Il primo comando con un singolo carattere e no <LF> non riesce a corrispondere, ma il secondo comando con 2 caratteri funziona correttamente, così come il terzo comando che ha un carattere con fine riga finale.

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

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

> echo x| findstr "^"
x

Segnalato dall'utente di DosTips Sponge Belly su nuovo bug findstr.Confermato su XP, Windows 7 e Windows 8.Non ho ancora sentito parlare di Vista.(Non ho più Vista da testare).

Sintassi delle opzioni
Le opzioni possono avere il prefisso entrambi / O -Le opzioni possono essere concatenate dopo un singolo / O -.Tuttavia, l'elenco di opzioni concatenate può contenere al massimo un'opzione a più caratteri come OFF o F: e l'opzione a più caratteri deve essere l'ultima opzione nell'elenco.

Quelli che seguono sono tutti modi equivalenti per esprimere una ricerca regex senza distinzione tra maiuscole e minuscole per qualsiasi riga che contenga sia "ciao" che "arrivederci" in qualsiasi ordine

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

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

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

Limiti di lunghezza della stringa di ricerca
Su Vista la lunghezza massima consentita per una singola stringa di ricerca è 511 byte.Se una stringa di ricerca supera 511, il risultato è a FINDSTR: Search string too long. errore con ERRORLEVEL 2.

Quando si esegue una ricerca con espressione regolare, la lunghezza massima della stringa di ricerca è 254.Un'espressione regolare con lunghezza compresa tra 255 e 511 risulterà in a FINDSTR: Out of memory errore con ERRORLEVEL 2.Una lunghezza di espressione regolare >511 risulta nel file FINDSTR: Search string too long. errore.

Su Windows XP la lunghezza della stringa di ricerca è apparentemente più breve. Errore Findstr:"Stringa di ricerca troppo lunga":Come estrarre e abbinare la sottostringa nel ciclo "for"?Il limite XP è 127 byte sia per le ricerche letterali che per quelle regex.

Limiti di lunghezza della linea
I file specificati come argomento della riga di comando o tramite l'opzione /F:FILE non hanno limiti di lunghezza di riga noti.Le ricerche sono state eseguite correttamente su un file da 128 MB che non conteneva un singolo <LF>.

I dati trasmessi e l'input reindirizzato sono limitati a 8191 byte per riga.Questo limite è una "caratteristica" di FINDSTR.Non è inerente alle pipe o al reindirizzamento.FINDSTR utilizzando stdin reindirizzato o input reindirizzato non corrisponderà mai a nessuna riga che sia> = 8k byte.Le righe >= 8k generano un messaggio di errore su stderr, ma ERRORLEVEL è ancora 0 se la stringa di ricerca viene trovata in almeno una riga di almeno un file.

Tipo di ricerca predefinito:Espressione letterale vs espressione regolare
/C:"string" - Il valore predefinito è /L letterale.Combinare esplicitamente l'opzione /L con /C:"string" funziona sicuramente ma è ridondante.

"string argument" - L'impostazione predefinita dipende dal contenuto della primissima stringa di ricerca. (Ricorda che <spazio> viene utilizzato per delimitare le stringhe di ricerca.) Se la prima stringa di ricerca è un'espressione regolare valida che contiene almeno un metacarattere senza escape, tutte le stringhe di ricerca vengono trattate come espressioni regolari.Altrimenti tutte le stringhe di ricerca vengono trattate come valori letterali.Per esempio, "51.4 200" verranno trattate come due espressioni regolari perché la prima stringa contiene un punto senza escape, mentre "200 51.4" verrà trattato come due valori letterali perché la prima stringa non contiene metacaratteri.

/G:file - L'impostazione predefinita dipende dal contenuto della prima riga non vuota del file.Se la prima stringa di ricerca è un'espressione regolare valida che contiene almeno un metacarattere senza escape, tutte le stringhe di ricerca vengono trattate come espressioni regolari.Altrimenti tutte le stringhe di ricerca vengono trattate come valori letterali.

Raccomandazione: specificare sempre esplicitamente /L opzione letterale o /R opzione di espressione regolare durante l'utilizzo "string argument" O /G:file.

BUG: specificare più stringhe di ricerca letterali può fornire risultati inaffidabili

Il seguente semplice esempio FINDSTR non riesce a trovare una corrispondenza, anche se dovrebbe.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Questo bug è stato confermato su Windows Server 2003, Windows XP, Vista e Windows 7.

Sulla base degli esperimenti, FINDSTR potrebbe non riuscire se vengono soddisfatte tutte le seguenti condizioni:

  • La ricerca utilizza più stringhe di ricerca letterali
  • Le stringhe di ricerca hanno lunghezze diverse
  • Una stringa di ricerca breve presenta una certa sovrapposizione con una stringa di ricerca più lunga
  • La ricerca distingue tra maiuscole e minuscole (n /I opzione)

In ogni errore che ho riscontrato, è sempre una delle stringhe di ricerca più brevi a fallire.

Per maggiori informazioni vedere Perché questo esempio FINDSTR con più stringhe di ricerca letterale non trova una corrispondenza?

Virgolette e barre rovesciate all'interno degli argomenti della riga di comando
Nota - I commenti dell'utente MC ND riflettono le attuali regole terribilmente complicate per questa sezione.Sono coinvolte 3 fasi di analisi distinte:

  • Innanzitutto cmd.exe potrebbe richiedere l'escape di alcune virgolette come ^" (in realtà niente a che fare con FINDSTR)
  • Successivamente FINDSTR utilizza il file Parser di argomenti MS C/C++ precedente al 2008, che ha regole speciali per " e \
  • Al termine dell'analisi degli argomenti, FINDSTR considera inoltre \ seguito da un carattere alfanumerico come letterale, ma \ seguito da un carattere non alfanumerico come carattere di escape

Il resto di questa sezione evidenziata non è corretta al 100%.Può servire da guida per molte situazioni, ma le regole di cui sopra sono necessarie per una comprensione totale.

Citazione di escape all'interno delle stringhe di ricerca della riga di comando
Le virgolette all'interno delle stringhe di ricerca della riga di comando devono essere precedute da una barra rovesciata \".Questo vale sia per le stringhe di ricerca letterali che per quelle regex.Questo informazioni sono state confermate su XP, Vista e Windows 7.

Nota:Potrebbe anche essere necessario eseguire l'escape delle virgolette per il parser CMD.EXE, ma ciò non ha nulla a che fare con FINDSTR.Ad esempio, per cercare un singola citazione si potrebbe usare:

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

Escape della barra rovesciata all'interno delle stringhe di ricerca letterale della riga di comando
La barra rovesciata in una stringa di ricerca letterale può normalmente essere rappresentata come \ o come \\.In genere sono equivalenti. (Ci possono essere inusuali casi in Vista dove il backslash deve sempre essere fuoriuscito, ma io no avere più a lungo una macchina Vista da testare).

Ma ci sono alcuni casi particolari:

Quando si cercano barre rovesciate consecutive, tutte tranne l'ultima dovere essere fuggito.Facoltativamente è possibile eseguire l'escape dell'ultima barra rovesciata.

  • \\ può essere codificato come \\\ O \\\\
  • \\\ può essere codificato come \\\\\ O \\\\\\

Cercare una o più barre rovesciate prima di una citazione è bizzarro.Logica suggerirebbe che la citazione deve essere sfuggito, e ciascuno dei principali Le backslashes dovrebbero essere evitate, ma questo non funziona!Invece, ciascuna delle backslash primarie deve essere doppiamente escape, e la virgoletta escape normalmente:

  • \" deve essere codificato come \\\\\"
  • \\" deve essere codificato come \\\\\\\\\"

Come notato in precedenza, anche una o più virgolette con escape potrebbero richiedere l'escape ^ per il parser CMD

Le informazioni contenute in questa sezione sono state confermate su XP e Windows 7.

Escape della barra rovesciata all'interno delle stringhe di ricerca regex della riga di comando

  • Solo Vista: La barra rovesciata in una regex deve essere doppiamente escape \\\\, oppure è stato eseguito un escape singolo all'interno di un set di classi di caratteri come [\\]

  • XP e Windows7: La barra rovesciata in una regex può sempre essere rappresentata come [\\].Normalmente può essere rappresentato come \\.Ma questo mai funziona se il backslash precede una virgoletta escape.

    Uno o più backslash prima di una virgoletta escape devono essere doppio escape, o altrimenti codificato come [\\]

    • \" può essere codificato come \\\\\" O [\\]\"
    • \\" può essere codificato come \\\\\\\\\" O [\\][\\]\" O \\[\\]\"

Escape di virgolette e barre rovesciate all'interno delle stringhe di ricerca letterali /G:FILE
Non è necessario che sia necessario eseguire l'escape delle virgolette e delle barre rovesciate autonome all'interno di un file di stringa di ricerca letterale specificato da /G:file, ma è possibile.

" E \" sono equivalenti.

\ E \\ sono equivalenti.

Se l'intento è trovare \\, è necessario eseguire l'escape almeno della barra rovesciata iniziale.Entrambi \\\ E \\\\ lavoro.

Se l'intento è trovare \", allora è necessario eseguire l'escape almeno della barra rovesciata iniziale.Entrambi \\" E \\\" lavoro.

Escape di virgolette e barre rovesciate all'interno delle stringhe di ricerca regex /G:FILE
Questo è l'unico caso in cui le sequenze di escape funzionano come previsto in base alla documentazione.La citazione non è un metacarattere regex, quindi non è necessario che sia necessario eseguire l'escape (ma può esserlo).La barra rovesciata è un metacarattere regex, quindi è necessario eseguire l'escape.

Limiti di caratteri per i parametri della riga di comando - Trasformazione ASCII estesa
Il carattere null (0x00) non può essere visualizzato in nessuna stringa sulla riga di comando.Nella stringa può essere presente qualsiasi altro carattere a byte singolo (0x01 - 0xFF).Tuttavia, FINDSTR converte molti caratteri ASCII estesi che trova nei parametri della riga di comando in altri caratteri.Ciò ha un impatto importante in due modi:

1) Molti caratteri ASCII estesi non corrisponderanno a se stessi se utilizzati come stringa di ricerca sulla riga di comando.Questa limitazione è la stessa per le ricerche letterali e regex.Se una stringa di ricerca deve contenere ASCII esteso, allora il file /G:FILE dovrebbe essere invece utilizzata l'opzione .

2) FINDSTR potrebbe non riuscire a trovare un file se il nome contiene caratteri ASCII estesi e il nome file è specificato sulla riga di comando.Se il file da cercare contiene ASCII esteso nel nome, allora il file /F:FILE dovrebbe essere invece utilizzata l'opzione .

Di seguito è riportato un elenco completo delle trasformazioni di caratteri ASCII estesi che FINDSTR esegue sulle stringhe della riga di comando.Ogni carattere è rappresentato come valore del codice byte decimale.Il primo codice rappresenta il carattere fornito sulla riga di comando e il secondo codice rappresenta il carattere in cui viene trasformato. Nota: questo elenco è stato compilato su una macchina statunitense.Non so quale impatto potrebbero avere altre lingue su questo elenco.

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

Qualsiasi carattere >0 non presente nell'elenco precedente viene trattato come se stesso, incluso <CR> e <LF>.Il modo più semplice per includere caratteri strani come <CR> E <LF> è inserirli in una variabile di ambiente e utilizzare l'espansione ritardata all'interno dell'argomento della riga di comando.

Limiti di caratteri per le stringhe trovate nei file specificati dalle opzioni /G:FILE e /F:FILE
Il carattere nul (0x00) può essere visualizzato nel file, ma funziona come il terminatore della stringa C.Tutti i caratteri dopo un carattere null vengono trattati come una stringa diversa, come se si trovassero su un'altra riga.

IL <CR> E <LF> i caratteri vengono trattati come terminatori di riga che terminano una stringa e non sono inclusi nella stringa.

Tutti gli altri caratteri a byte singolo sono inclusi perfettamente all'interno di una stringa.

Ricerca di file Unicode
FINDSTR non può cercare correttamente la maggior parte dei byte Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) perché non può cercare byte null e Unicode in genere contiene molti byte null.

Tuttavia, il comando TYPE converte UTF-16LE con BOM in un set di caratteri a byte singolo, quindi un comando come il seguente funzionerà con UTF-16LE con BOM.

type unicode.txt|findstr "search"

Tieni presente che i punti di codice Unicode non supportati dalla tabella codici attiva verranno convertiti in ? caratteri.

È possibile eseguire la ricerca in UTF-8 purché la stringa di ricerca contenga solo ASCII.Tuttavia, l'output della console di qualsiasi carattere UTF-8 multibyte non sarà corretto.Ma se reindirizzi l'output su un file, il risultato verrà codificato correttamente UTF-8.Tieni presente che se il file UTF-8 contiene una distinta base, la distinta base verrà considerata come parte della prima riga, il che potrebbe impedire una ricerca che corrisponda all'inizio di una riga.

È possibile eseguire la ricerca di caratteri UTF-8 multibyte se si inserisce la stringa di ricerca in un file di ricerca con codifica UTF-8 (senza BOM) e si utilizza l'opzione /G.

Fine della linea
FINDSTR interrompe le righe immediatamente dopo ogni <LF>.La presenza o l'assenza di <CR> non ha alcun impatto sulle interruzioni di riga.

Ricerca attraverso le interruzioni di riga
Come previsto, il . il metacarattere regex non corrisponderà a <CR> o <LF>.Ma è possibile effettuare una ricerca attraverso un'interruzione di riga utilizzando una stringa di ricerca da riga di comando.Entrambi i caratteri <CR> e <LF> devono essere abbinati in modo esplicito.Se viene trovata una corrispondenza su più righe, viene stampata solo la prima riga della corrispondenza.FINDSTR torna quindi alla seconda riga del sorgente e ricomincia la ricerca da capo, una sorta di funzionalità di tipo "guarda avanti".

Supponiamo che TEXT.TXT abbia questi contenuti (potrebbe essere in stile Unix o Windows)

A
A
A
B
A
A

Quindi questo copione

@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

dà questi risultati

1:A
2:A
5:A

La ricerca tra interruzioni di riga utilizzando l'opzione /G:FILE è imprecisa perché l'unico modo per trovare <CR> o <LF> è tramite un'espressione di intervallo di classi di caratteri regex che racchiude i caratteri EOL.

  • [<TAB>-<0x0B>] corrisponde a <LF>, ma corrisponde anche a <TAB> e

  • [<0x0C>-!] corrisponde a <CR>, ma corrisponde anche a e !

    Nota: quanto sopra sono rappresentazioni simboliche del flusso di byte regex poiché non posso rappresentare graficamente i caratteri.

La risposta continua nella parte 2 di seguito...

Altri suggerimenti

Risposta Continua dalla parte 1 sopra - Ho incontrato il limite di risposta dei 30.000 caratteri :-(

Supporto espressioni regolari limitate (Regex)
Il supporto di Findstr per espressioni regolari è estremamente limitato. Se non è nella documentazione di aiuto, non è supportato.

Oltre a ciò, le espressioni di regex supportate sono implementate in modo completamente non standard, in modo tale che i risultati possano essere diversi, quindi ci si aspetterebbe che provengano da qualcosa come Grep o Perl.

REGEX Line Position Anchors ^ e $
^ corrisponde all'inizio del flusso di input e a qualsiasi posizione immediatamente dopo unu003CLF> . Dal momento che Findstr interrompe anche le linee dopou003CLF> , un semplice regex di "^" corrisponderà sempre a tutte le righe all'interno di un file, persino un file binario.

$ corrisponde a qualsiasi posizione immediatamente precedente au003CCR> . Ciò significa che una stringa di ricerca regex contenente $ non corrisponderà mai a nessuna riga all'interno di un file di testo in stile Unix, né corrisponderà all'ultima riga di un file di testo di Windows se manca il marcatore EOL diu003CCR>u003CLF> .

Nota: come discusso in precedenza, può avere input di tubazione e reindirizzamento a Findstr <CR><LF> Aggiunto che non è nella fonte. Ovviamente questo può avere un impatto su una ricerca regex che usa $.

Qualsiasi stringa di ricerca con i caratteri prima ^ o dopo $ non riuscirà sempre a trovare una partita.

Opzioni posizionali /b /e /x
Le opzioni posizionali funzionano allo stesso modo di ^ e $, tranne che lavorano anche per stringhe di ricerca letterale.

/B funziona come ^ All'inizio di una stringa di ricerca Regex.

/E funziona come $ Alla fine di una stringa di ricerca Regex.

/X funziona come avere entrambi ^ All'inizio e $ Alla fine di una stringa di ricerca Regex.

Regex Word Boundary
\< Deve essere il primo termine nel regex. Il regex non corrisponderà a nulla se altri personaggi lo precedono. \< corrisponde all'inizio dell'ingresso, l'inizio di una riga (la posizione immediatamente seguendo au003CLF> ) o la posizione immediatamente seguendo qualsiasi personaggio "non-parola". Il personaggio successivo non deve essere un personaggio di "parola".

\> Deve essere l'ultimo termine nel regex. Il regex non corrisponderà a nulla se altri personaggi lo seguono. \> corrisponde a entrambe le estremità dell'input, la posizione immediatamente prima di unu003CCR> o la posizione immediatamente precedente a qualsiasi personaggio "non-parole". Il personaggio precedente non deve essere un personaggio di "parola".

Ecco un elenco completo di caratteri "non di parola", rappresentato come codice byte decimale. Nota: questo elenco è stato compilato su una macchina USA. Non so quale impatto potrebbero avere altre lingue in questo elenco.

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 CLASS CLASS RANGE [XY
Gli intervalli di classe di personaggi non funzionano come previsto. Vedi questa domanda: Perché Findstr non gestisce il caso correttamente (in alcune circostanze)?, insieme a questa risposta: https://stackoverflow.com/a/8767815/1012053.

Il problema è che Findstr non raccoglie i caratteri dal valore del codice byte (comunemente pensato come codice ASCII, ma ASCII è definito solo da 0x00 - 0x7f). La maggior parte delle implementazioni di regex tratterebbe [AZ] come tutte le lettere maiuscole inglesi. Ma Findstr utilizza una sequenza di raccolta che corrisponde approssimativamente a come funziona l'ordinamento. Quindi [AZ] include l'alfabeto inglese completo, sia superiore che minuscolo (ad eccezione di "A"), nonché caratteri alfa non inglesi con diacritici.

Di seguito è riportato un elenco completo di tutti i caratteri supportati da Findstr, ordinato nella sequenza di raccolta utilizzata da Findstr per stabilire gamme di classi di caratteri Regex. I caratteri sono rappresentati come valore del codice byte decimale. Credo che la sequenza di raccolta abbia più senso se i caratteri vengono visualizzati usando il codice Pagina 437. Nota: questo elenco è stato compilato su una macchina USA. Non so quale impatto potrebbero avere altre lingue in questo elenco.

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 CLASS CLASS CLASSE LIMITO E BUG
Non solo la ricerca è limitata a un massimo di 15 termini di classe di caratteri all'interno di un regex, ma non riesce a gestire correttamente un tentativo di superare il limite. L'uso di 16 o più termini di classe di caratteri si traduce in un pop -up di Windows interattivo affermando "Trova l'utilità String (QGREP) ha riscontrato un problema e deve chiudere. Ci scusiamo per l'inconveniente." Il testo del messaggio varia leggermente a seconda della versione di Windows. Ecco un esempio di una ricerca che fallirà:

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]

Questo bug è stato segnalato dall'utente di Dostips Giuda qui. È stato confermato su XP, Vista e Windows 7.

Le ricerche regex falliscono (e possono appendere indefinitamente) se includono il codice byte 0xFF (decimale 255)
Qualsiasi ricerca regex che include il codice byte 0xFF (decimale 255) fallirà. Non riesce se il codice byte 0xFF è incluso direttamente o se è implicitamente incluso all'interno di un intervallo di classi di caratteri. Ricorda che le gamme di classi di caratteri Findstr non raccolgono caratteri in base al valore del codice byte. Carattere <0xFF> appare relativamente presto nella sequenza di raccolta tra il <space> e <tab> personaggi. Quindi qualsiasi gamma di classi di personaggi che include entrambi <space> e <tab> avrà esito negativo.

Il comportamento esatto cambia leggermente a seconda della versione di Windows. Windows 7 è appeso indefinitamente se è incluso 0xFF. XP non è appeso, ma non riesce sempre a trovare una corrispondenza e occasionalmente stampa il seguente messaggio di errore - "Il processo ha cercato di scrivere su una pipa inesistente."

Non ho più accesso a una macchina per Vista, quindi non sono stato in grado di testare Vista.

REGEX BUG: . e [^anySet] può abbinare la fine del file
Il regex . Il meta-caratteri dovrebbe corrispondere solo a qualsiasi personaggio diverso da <CR> o <LF>. C'è un bug che gli consente di abbinare la fine del file se l'ultima riga nel file non è terminata da <CR> o <LF>. in ogni caso, il . non corrisponderà a un file vuoto.

Ad esempio, un file denominato "test.txt" contenente una singola riga di x, senza terminare <CR> o <LF>, corrisponderà a quanto segue:

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

Questo bug è stato confermato su XP e Win7.

Lo stesso sembra essere vero per i set di caratteri negativi. Qualcosa di simile a [^abc] corrisponderà a fine file. Set di caratteri positivi come [abc] sembra funzionare bene. L'ho provato solo su Win7.

findstr A volte pende inaspettatamente quando si cerca file di grandi dimensioni.

Non ho confermato le condizioni esatte o le dimensioni dei confini. Sospetto che qualsiasi file più grande 2 GB possa essere a rischio.

Ho avuto esperienze contrastanti con questo, quindi è più che una semplice dimensione del file. Sembra che potrebbe essere una variazione Findstr è appeso su XP e Windows 7 se l'ingresso reindirizzato non termina con LF, ma come dimostrato questo particolare problema si manifesta quando l'input lo è non reindirizzato.

La seguente sessione della riga di comando (Windows 7) dimostra come findstr può appendere quando si cerca un file da 3 GB.

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>

Nota, ho verificato in un editor esadecimale con cui tutte le righe sono terminate CRLF. L'unica anomalia è che il file viene terminato 0x1A a causa di il modo copy lavori. Nota tuttavia che questa anomalia non causa un problema su file "piccoli".

Con ulteriori test ho confermato quanto segue:

  • Usando copy con il /b L'opzione per i file binari impedisce l'aggiunta del 0x1A carattere, e findstr Non è appeso al file da 3 GB.
  • Terminare il file da 3 GB con un carattere diverso provoca anche a findstr appendere.
  • Il 0x1A Il personaggio non provoca problemi su un file "piccolo". (Analogamente per altri caratteri terminanti.)
  • Aggiunta CRLF dopo 0x1A risolve il problema. (LF di per sé sarebbe probabilmente sufficiente.)
  • Usando type per pipì il file in findstr Funziona senza appendere. (Ciò potrebbe essere dovuto a un effetto collaterale di entrambi type o | che inserisce un'estremità aggiuntiva della linea.)
  • Utilizzare l'input reindirizzato < Cause anche findstr appendere. Ma questo è previsto; come spiegato in Post di Dbenham: "L'input reindirizzato deve finire LF".

Quando diversi comandi sono racchiusi tra parentesi e ci sono file reindirizzati all'intero blocco:

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

... Quindi i file rimangono aperti fintanto che i comandi nel blocco siano attivi, quindi i comandi possono spostare il puntatore del file dei file reindirizzati. Sia più che i comandi trovano spostano il puntatore del file stdin all'inizio del file prima di elaborarlo, quindi lo stesso file può essere elaborato più volte all'interno del blocco. Ad esempio, questo codice:

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

... produrre lo stesso risultato di questo:

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

Questo codice:

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

... produrre lo stesso risultato di questo:

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

Findstr è diverso; lo fa non Spostare il puntatore del file stdin dalla sua posizione attuale. Ad esempio, questo codice inserisce una nuova riga dopo una riga di ricerca:

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

Potremmo sfruttare questo funzionalità con l'aiuto di un programma ausiliario che ci consente di spostare il puntatore del file di un file reindirizzato, come mostrato in questo esempio.

Questo comportamento è stato riportato per la prima volta da jeb a questo post.


Modifica 2018-08-18: Nuovo bug Findstr riportato

Il comando Findstr ha uno strano bug che si verifica quando questo comando viene utilizzato per mostrare i caratteri a colori e l'output di tale comando viene reindirizzato al dispositivo Con. Per i dettagli su come utilizzare il comando findstr per mostrare il testo a colore, vedi questo argomento.

Quando l'output di questa forma di comando Findstr viene reindirizzato a Con, succede qualcosa di strano dopo che il testo viene emesso nel colore desiderato: tutto il testo dopo che è stato emesso come caratteri "invisibili", sebbene una descrizione più precisa sia che il testo è Output come testo nero su sfondo nero. Il testo originale verrà visualizzato se si utilizza il comando colore per ripristinare il primo piano e i colori di sfondo dell'intero schermo. Tuttavia, quando il testo è "invisibile" potremmo eseguire un comando set /p, quindi tutti i caratteri inseriti non appariranno sullo schermo. Questo comportamento può essere utilizzato per inserire le password.

@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%"

Vorrei segnalare un bug per quanto riguarda la sezione Fonte di dati da cercare Nella prima risposta quando si usa en cruscola (-) o Em Dash ( -) all'interno del nome file.

Più specificamente, se stai per utilizzare la prima opzione - Farmate specificate come argomenti, il file non verrà trovato. Non appena usi entrambe le opzioni 2 - stdin tramite reindirizzamento o 3 - flusso di dati da un tubo, Findstr troverà il file.

Ad esempio, questo semplice script batch:

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

Stamparrà:

Nome file con en dash:

  1. Come argomento
    Findstr: Impossibile aprire il nome file con - Dash.txt

  2. Come stdin tramite reindirizzamento
    Sono il file con un trattino.

  3. Come dati di dati da un tubo
    Sono il file con un trattino.

FileName con EM Dash:

  1. Come argomento
    Findstr: Impossibile aprire il nome file con - Dash.txt

  2. Come stdin tramite reindirizzamento
    Sono il file con un trattino EM.

  3. Come dati di dati da un tubo
    Sono il file con un trattino EM.

Spero che sia d'aiuto.

M.

Il findstr comando Imposta il ErrorLevel (o codice di uscita) a uno dei seguenti valori, dato che non ci sono switch non validi o incompatibili e nessuna stringa di ricerca supera il limite di lunghezza applicabile:

  • 0 quando almeno una singola corrispondenza viene riscontrata in una riga in tutti i file specificati;
  • 1 altrimenti;

Si considera una linea per contenere una corrispondenza quando:

  • No /V Viene data l'opzione e l'espressione di ricerca si verifica almeno una volta;
  • il /V viene data l'opzione e l'espressione della ricerca non si verifica;

Questo significa che il /V l'opzione cambia anche il restituito ErrorLevel, ma lo fa non Ripristinalo!

Ad esempio, quando hai un file test.txt con due righe, una delle quali contiene la stringa text Ma l'altro no, entrambi findstr "text" "test.txt" e findstr /V "text" "test.txt" restituire un ErrorLevel di 0.

Fondamentalmente puoi dire: se findstr restituisce almeno una riga, ErrorLevel è impostato per 0, altro a 1.

Nota che il /M l'opzione non influisce sul ErrorLevel Valuta, altera solo l'output.

(Solo per la completezza: il find comando si comporta esattamente allo stesso modo rispetto al /V opzione e ErrorLevel; il /C L'opzione non influisce su ErrorLevel.)

/D Suggerimento per più directory: inserire l'elenco delle directory prima della stringa di ricerca. Tutti questi funzionano:

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

Come previsto, il percorso è relativo alla posizione se non si avvia le directory con \. Circostante il percorso con " è facoltativo se non ci sono spazi nei nomi della directory. Il finale \ è facoltativo. L'output della posizione includerà qualsiasi percorso che gli dai. Funzionerà con o senza circondare l'elenco delle directory con ".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top