Quali sono le funzionalità e i limiti non documentati del comando FINDSTR di Windows?


188

Il comando FINDSTR di Windows è orribilmente documentato. È disponibile una guida di riga di comando molto semplice tramite FINDSTR /?o HELP FINDSTR, ma è terribilmente inadeguata. 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 FINDSTR che non sono nemmeno accennate nella documentazione. Né potevano essere anticipati senza una conoscenza preliminare e / o un'attenta sperimentazione.

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

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

A) 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 dall'Help, non appartengono qui.

Né questo è un posto per mostrare usi interessanti di FINDSTR. Se una persona logica potrebbe anticipare il comportamento di un particolare utilizzo di FINDSTR in base alla documentazione, allora non appartiene a questo.

Allo stesso modo, se una persona logica potrebbe anticipare il comportamento di un particolare utilizzo in base alle informazioni contenute in qualsiasi risposta esistente, allora di nuovo, non appartiene a questo.


15
Oppure, in alternativa, potresti abbandonare del tutto la pessima utility MS non documentata e installare / utilizzare grepche è molto ben compreso e documentato :-) Vedi stackoverflow.com/questions/2635740/… per esempio.
paxdiablo,

17
In ogni caso, se si è in grado di utilizzare qualcosa di diverso da FINDSTR, questo è altamente consigliato. Ma alcune persone si trovano in ambienti in cui sono vietate utility di terze parti.
dbenham,

4
Nessuna offesa. Ho preso seriamente in considerazione l'idea di inserire il mio disclaimer FINDSTR simile al tuo commento! :)
dbenham,

41
Sono scioccato e deluso dal fatto che qualcuno troverebbe questa domanda "Non costruttiva" e voterebbe per chiudere. Molta riflessione è stata posta in particolare sulla domanda per evitare "opinioni, dibattiti, discussioni, sondaggi o discussioni estese". La domanda è stata pubblicata per 3,5 mesi e nessuno dei negativi citati si è verificato. La risposta accoppiata è piena di fatti e ha richiesto molte ore di scrupolosa ricerca e sperimentazione.
dbenham,

6
Alcuni lettori potrebbero essere interessati al contesto storico del comando findstr
Harry Johnston,

Risposte:


279

Prefazione
Molte delle informazioni contenute in questa risposta sono state raccolte sulla base di esperimenti condotti su una macchina Vista. Se non diversamente specificato, non ho confermato se le informazioni si applicano ad altre versioni di Windows.

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

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

filename: lineNumber: lineOffset: il testo

dove

fileName: = 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 cercava l'input del pip o l'input reindirizzato. Quando viene stampato, il fileName includerà sempre tutte le informazioni sul percorso fornite. Ulteriori informazioni sul percorso verranno aggiunte se/Ssi utilizzal'opzione. Il percorso stampato è sempre relativo al percorso fornito, o relativo alla directory corrente se non fornito.

Nota: il prefisso del nome file può essere evitato durante la ricerca di più file utilizzando i caratteri jolly non standard (e scarsamente documentati) < e >. Le regole esatte su come funzionano questi caratteri jolly sono disponibili qui . Infine, puoi vedere questo esempio di come funzionano i caratteri jolly non standard con FINDSTR .

lineNumber: = Il numero di riga della riga corrispondente rappresentata come valore decimale con 1 che rappresenta la 1a riga dell'input. Stampato solo se l'/Nopzione è specificata.

lineOffset: = Offset del byte decimale dell'inizio della riga corrispondente, con 0 che rappresenta il 1 ° carattere della 1a riga. Stampato solo se l'/Oopzione è specificata. Questo non èl'offset della corrispondenza all'interno della linea. È il numero di byte dall'inizio del file all'inizio della riga.

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

FINDSTR "^" FILE >FILE_COPY

L'opzione / A imposta il colore del fileName :, lineNumber: e lineOffset: solo output. Il testo della riga corrispondente viene sempre emesso con il colore corrente della console. L'opzione / A ha effetto solo quando l'output viene visualizzato direttamente sulla console. L'opzione / A non ha alcun effetto se l'output viene reindirizzato a un file o reindirizzato. Vedi la modifica 2018-08-18 nella risposta di Aacini per una descrizione del comportamento errato quando l'output viene reindirizzato a CON.

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 carrello 0x0D.

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

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

Vista e Windows 7 mostrano sempre tutti i personaggi come se stessi, mai come punti.

Codici di ritorno (ERRORLEVEL)

  • 0 (successo)
    • La corrispondenza è stata trovata in almeno una riga di almeno un file.
  • 1 (fallimento)
    • Nessuna corrispondenza trovata in nessuna riga di alcun file.
    • Colore non valido specificato /A:xxdall'opzione
  • 2 (errore)
    • Opzioni incompatibili /Led /Rentrambe specificate
    • Manca argomento dopo /A:, /F:, /C:, /D:, o/G:
    • File specificato da /F:fileo /G:filenon 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 fonti:

  • nomi di file specificati come argomenti e / o usando l' /F:fileopzione.

  • stdin tramite reindirizzamento findstr "searchString" <file

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

Argomenti / opzioni hanno la precedenza sul reindirizzamento, che ha la precedenza sui dati convogliati.

Argomenti del nome file e /F:filepossono essere combinati. È possibile utilizzare più argomenti per i nomi di file. Se /F:filevengono specificate più opzioni, viene utilizzata solo l'ultima. I caratteri jolly sono consentiti negli argomenti del nome 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)
Le opzioni /G:filee /C:stringpossono essere combinate. /C:stringÈ possibile specificare più opzioni. Se /G:filevengono specificate più opzioni, viene utilizzata solo l'ultima. Se si utilizza uno /G:fileo entrambi /C:string, si presume che tutti gli argomenti non di opzione siano file da cercare. Se né /G:filenor né /C:stringviene utilizzato, il primo argomento non opzione viene trattato come un elenco delimitato da spazi di termini di ricerca.

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

ERRORE - I nomi di file 8.3 brevi possono interrompere le opzioni /De/S
Come per tutti i comandi di Windows, FINDSTR tenterà di far corrispondere sia il nome lungo che il nome breve 8.3 quando si cercano 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.txt2corrisponde perché corrisponde il nome breve B9F64~1.TXTcorrispondente. Ciò è coerente con il comportamento di tutti gli altri comandi di Windows.

Ma un bug con le opzioni /De /Sfa sì che vengano trovati solo i seguenti comandib1.txt

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

Il bug impedisce b.txt2di essere trovato, così come tutti i nomi di file che ordinano dopo b.txt2all'interno della stessa directory. a.txtSi trovano file aggiuntivi che prima ordinano, ad esempio . 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, l' /Sopzione inizierà a cercare correttamente in una cartella figlio dopo che non è stato possibile trovare i file nel genitore, ma una volta che il bug fa perdere un nome di file breve nel figlio, anche tutti i file successivi in ​​quella cartella figlio mancherebbero .

I comandi funzionano senza errori se gli stessi nomi di file vengono creati su un computer in cui la generazione di nomi NTFS 8.3 è disabilitata. Naturalmente b.txt2non sarebbe stato trovato, ma c.txtsarebbe stato trovato correttamente.

Non tutti i nomi brevi attivano il bug. Tutte le istanze di comportamento errato che ho visto coinvolgono un'estensione più lunga di 3 caratteri con un breve nome 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 l' /Popzione
L' /Popzione fa sì che FINDSTR salti qualsiasi file contenente uno dei seguenti codici byte decimali:
0-7, 14-25, 27-31.

Detto in altro modo, l' /Popzione salterà solo i file che contengono caratteri di controllo non stampabili. I caratteri di controllo sono codici inferiori o uguali a 31 (0x1F). FINDSTR tratta i seguenti caratteri di controllo come stampabili:

 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 provoca l' /Popzione per saltare il file.

È possibile che sia stato <CR><LF>aggiunto input reindirizzato e reindirizzato
Se l'input è reindirizzato e l'ultimo carattere del flusso non lo è <LF>, FINDSTR verrà automaticamente aggiunto <CR><LF>all'input. 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 facendo 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 si aggiungerà automaticamente <CR><LF>all'input. 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 "funzione" su XP e Windows 7. Se l'ultimo carattere di un file utilizzato come input reindirizzato non termina con <LF>, FINDSTR si bloccherà indefinitamente una volta raggiunge la fine del file reindirizzato.

L'ultima riga di dati Piped può essere ignorata se è composta da un singolo carattere
Se l'input è reindirizzato e l'ultima riga è composta da un singolo carattere non seguito da <LF>, FINDSTR ignora completamente l'ultima riga.

Esempio - Il primo comando con un singolo carattere e nessun <LF>errore non corrisponde, ma il secondo comando con 2 caratteri funziona bene, così come il terzo comando che ha un carattere con la fine della nuova riga.

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

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

> echo x| findstr "^"
x

Segnalato dall'utente Sponge Belly di DosTips al 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 È possibile aggiungere un prefisso alle opzioni /oppure Le -opzioni possono essere concatenate dopo una singola /o -. Tuttavia, l'elenco di opzioni concatenate può contenere al massimo un'opzione multi-carattere come OFF o F :, e l'opzione multi-carattere deve essere l'ultima opzione dell'elenco.

I seguenti sono tutti modi equivalenti di esprimere una ricerca regex insensibile al maiuscolo / minuscolo per qualsiasi riga che contenga sia "ciao" che "addio" 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 è un FINDSTR: Search string too long.errore con ERRORLEVEL 2.

Quando si esegue una ricerca di espressioni regolari, la lunghezza massima della stringa di ricerca è 254. Un'espressione regolare con lunghezza compresa tra 255 e 511 comporterà un FINDSTR: Out of memoryerrore con ERRORLEVEL 2. Una lunghezza di espressione regolare> 511 determina l' FINDSTR: Search string too long.errore.

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

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

I dati in pipe 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 che utilizza lo stdin reindirizzato o l'input di piping non corrisponderà mai a nessuna riga che è> = 8k byte. Righe> = 8k generano un messaggio di errore per stderr, ma ERRORLEVEL è ancora 0 se la stringa di ricerca viene trovata in almeno una riga di almeno un file.

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

"string argument"- L'impostazione predefinita dipende dal contenuto della prima 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 meta-carattere senza escape, tutte le stringhe di ricerca vengono trattate come espressioni regolari. In caso contrario, tutte le stringhe di ricerca vengono trattate come valori letterali. Ad esempio, "51.4 200"verranno trattate come due espressioni regolari perché la prima stringa contiene un punto senza escape, mentre "200 51.4"verranno trattate come due letterali perché la prima stringa non contiene alcun meta-carattere.

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

Raccomandazione: specificare sempre esplicitamente /Ll'opzione letterale o /Rl'opzione di espressione regolare quando si utilizza "string argument"o /G:file.

ERRORE: la specifica di più stringhe di ricerca letterali può dare risultati inaffidabili

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

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

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

Sulla base di esperimenti, FINDSTR potrebbe fallire se sono 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 ha una certa quantità di sovrapposizione con una stringa di ricerca più lunga
  • La ricerca fa distinzione tra maiuscole e minuscole (nessuna /Iopzione)

In ogni errore che ho visto, è sempre una delle stringhe di ricerca più brevi che non riesce.

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

Citazioni e backslahses all'interno degli argomenti della riga di comando
Nota - I commenti dell'utente MC ND riflettono le attuali regole orribilmente complicate per questa sezione. Sono previste 3 distinte fasi di analisi:

  • Il primo cmd.exe potrebbe richiedere l'escape di alcune virgolette come ^ "(davvero niente a che fare con FINDSTR)
  • Il prossimo FINDSTR utilizza il parser di argomenti MS C / C ++ precedente al 2008 , che ha regole speciali per "e \
  • Al termine dell'argomento parser, 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 è corretto al 100%. Può servire come guida per molte situazioni, ma le regole di cui sopra sono necessarie per una comprensione totale.

Preventivo 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 salvate con una barra rovesciata come \". Questo è vero sia per le stringhe di ricerca letterale che regex. Queste informazioni sono state confermate su XP, Vista e Windows 7.

Nota: potrebbe essere necessario eseguire l'escape della citazione per il parser CMD.EXE, ma ciò non ha nulla a che fare con FINDSTR. Ad esempio, per cercare una singola citazione è possibile utilizzare:

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

Escaping della barra rovesciata all'interno delle stringhe di ricerca letterali della riga di comando La
barra rovesciata in una stringa di ricerca letterale può normalmente essere rappresentata come \o come \\. Sono in genere equivalenti. (Ci possono essere casi insoliti in Vista in cui la barra rovesciata deve sempre essere sfuggita, ma non ho più una macchina Vista da testare) .

Ma ci sono alcuni casi speciali:

Quando si cercano barre rovesciate consecutive, è necessario sfuggire a tutti tranne l'ultimo . L'ultima barra rovesciata può facoltativamente essere salvata.

  • \\può essere codificato come \\\o\\\\
  • \\\può essere codificato come \\\\\o\\\\\\

La ricerca di una o più barre rovesciate prima di un preventivo è bizzarra. La logica suggerirebbe che il preventivo debba essere evitato e che ognuna delle barre rovesciate principali debba essere evasa, ma questo non funziona! Invece, ciascuna delle barre rovesciate principali deve essere doppiamente esclusa e la citazione viene evitata normalmente:

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

Come notato in precedenza, una o più virgolette con escape possono richiedere anche la escape con ^per il parser CMD

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

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

  • Solo Vista: la barra rovesciata in una regex deve essere come doppia escape \\\\, oppure come singola escape all'interno di una classe di caratteri impostata come [\\]

  • XP e Windows 7: la barra rovesciata in una regex può sempre essere rappresentata come [\\]. Normalmente può essere rappresentato come \\. Ma questo non funziona mai se la barra rovesciata precede una citazione salvata.

    Una o più barre rovesciate prima di una citazione con escape devono essere con doppio escape oppure devono essere codificate come [\\]

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

Virgolette di escape e barra rovesciata all'interno di / G: stringhe di ricerca letterali FILE Virgolette e
barre rovesciate all'interno di un file di stringa di ricerca letterale specificato da / G: il file non deve essere sottoposto a escape, ma possono esserlo.

"e \"sono equivalenti.

\e \\sono equivalenti.

Se l'intento è trovare \\, almeno la barra rovesciata iniziale deve essere sfuggita. Entrambi \\\e \\\\funzionano.

Se l'intento è trovare \ ", almeno la barra rovesciata principale deve essere sfuggita. Entrambi \\"e \\\"funzionano.

Quote di escape e barra rovesciata all'interno di / G: stringhe di ricerca regex FILE
Questo è il caso in cui le sequenze di escape funzionano come previsto in base alla documentazione. La citazione non è un metacarattere regex, quindi non deve essere evitato (ma può esserlo). La barra rovesciata è un metacarattere regex, quindi deve essere evitato.

Limiti di caratteri per i parametri della riga di comando - Trasformazione ASCII estesa
Il carattere null (0x00) non può apparire in nessuna stringa sulla riga di comando. Qualsiasi altro carattere a byte singolo può apparire nella stringa (0x01 - 0xFF). Tuttavia, FINDSTR converte molti caratteri ASCII estesi che trova all'interno dei parametri della riga di comando in altri caratteri. Ciò ha un impatto notevole in due modi:

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

2) FINDSTR potrebbe non riuscire a trovare un file se il nome contiene caratteri ASCII estesi e il nome del file è specificato nella riga di comando. Se un file da cercare contiene ASCII esteso nel nome, /F:FILEè preferibile utilizzare l' opzione.

Ecco un elenco completo delle trasformazioni di caratteri ASCII estese che FINDSTR esegue sulle stringhe della riga di comando. Ogni carattere è rappresentato come valore decimale del codice byte. Il primo codice rappresenta il carattere come fornito sulla riga di comando e il secondo codice rappresenta il carattere in cui viene trasformato. Nota: questo elenco è stato compilato su una macchina americana. Non so quale impatto potrebbero avere altre lingue in 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, inclusi <CR>e < LF>. Il modo più semplice per includere caratteri dispari come <CR>ed <LF>è inserirli in una variabile di ambiente e utilizzare l'espansione ritardata nell'argomento della riga di comando.

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

I caratteri <CR>e <LF>sono 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 in una stringa.

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

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"

Nota che i punti di codice Unicode che non sono supportati dalla tua tabella codici attiva verranno convertiti in ?caratteri.

È possibile cercare UTF-8 purché la stringa di ricerca contenga solo ASCII. Tuttavia, l'output della console di qualsiasi carattere UTF-8 multi-byte non sarà corretto. Ma se si reindirizza l'output su un file, il risultato verrà codificato correttamente UTF-8. Si noti che se il file UTF-8 contiene una DBA, la DBA verrà considerata come parte della prima riga, che potrebbe annullare una ricerca che corrisponde all'inizio di una riga.

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

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

Ricerca tra le interruzioni di riga
Come previsto, il .metacarattere regex non corrisponderà a <CR> o <LF>. Ma è possibile cercare attraverso un'interruzione di riga usando una stringa di ricerca della riga di comando. Entrambi i caratteri <CR> e <LF> devono essere abbinati esplicitamente. Se viene trovata una corrispondenza su più righe, viene stampata solo la prima riga della corrispondenza. FINDSTR quindi raddoppia alla seconda riga nella sorgente e ricomincia la ricerca da capo - una sorta di funzione 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 questa sceneggiatura

@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 le interruzioni di riga utilizzando l'opzione / G: FILE è imprecisa perché l'unico modo per abbinare <CR> o <LF> è tramite un'espressione di intervallo di classi di caratteri regex che inserisce i caratteri EOL.

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

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

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

Risposta continua nella parte 2 di seguito ...


46
Completezza eccezionale. Se solo tutte le risposte su Internet fossero così.
Mike Viens,

1
abbiamo incontrato un problema con addpath.batda Q141344 e findstr, che può essere correlato al problema impiccagione Win7 di cui sopra. Ho creato una chat room per provare a rintracciarla, per chiunque sia interessato: chat.stackoverflow.com/rooms/13177/…
matt wilkie,

2
EDIT - Descritta la visualizzazione dei caratteri di controllo come punti su XP. Sono stati inoltre documentati errori /Se /Dopzioni derivanti da nomi di file 8.3 brevi.
dbenham,

1
EDIT - 1) I nomi dei file all'interno del file specificato da / F: FILE non devono essere quotati. 2) La trasformazione di caratteri ASCII estesi influisce sia sulle stringhe di ricerca sia sui nomi dei file quando viene fornita sulla riga di comando.
dbenham,

1
EDIT - Aggiunto bug in cui l'ultima riga dell'input di piping viene ignorata se è composta da un singolo carattere senza<LF>
dbenham

64

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

Supporto
per espressioni regolari limitate (regex) Il supporto FINDSTR per le espressioni regolari è estremamente limitato. Se non è presente nella documentazione HELP, non è supportato.

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

Le ancore Posizione riga Regex ^ e $
^ corrispondono all'inizio del flusso di input e a qualsiasi posizione immediatamente successiva a <LF>. Poiché FINDSTR interrompe anche le righe dopo <LF>, una semplice regex di "^" corrisponderà sempre a tutte le righe di un file, anche a un file binario.

$corrisponde a qualsiasi posizione immediatamente precedente a <CR>. 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 Windows se manca il marcatore EOL di <CR> <LF>.

Nota - Come precedentemente discusso, l'input reindirizzato e reindirizzato a FINDSTR potrebbe aver <CR><LF>aggiunto che non si trova nell'origine. Ovviamente questo può influire su una ricerca regex che utilizza $.

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

Opzioni di posizione / B / E / X
Le opzioni di posizione funzionano allo stesso modo di ^e $, tranne per le stringhe di ricerca letterali.

/ 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 se fosse ^all'inizio e $alla fine di una stringa di ricerca regex.

Il limite delle parole Regex
\< deve essere il primo termine della regex. La regex non corrisponderà a nulla se nessun altro personaggio lo precede. \<corrisponde all'inizio dell'ingresso, all'inizio di una riga (la posizione immediatamente successiva a <LF>) o alla posizione immediatamente successiva a qualsiasi carattere "non-parola". Il personaggio successivo non deve necessariamente essere un carattere "parola".

\>deve essere l'ultimo termine della regex. La regex non corrisponderà a nulla se nessun altro personaggio lo segue. \>corrisponde alla fine dell'input, alla posizione immediatamente precedente a un <CR> o alla posizione immediatamente precedente a qualsiasi carattere "non-parola". Il carattere precedente non deve necessariamente essere un carattere "parola".

Ecco un elenco completo di caratteri "non-word", rappresentati come codice byte decimale. Nota: questo elenco è stato compilato su una macchina americana. 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

Intervalli di classi di caratteri Regex [xy]
Gli intervalli di classi di caratteri non funzionano come previsto. Vedi questa domanda: Perché findstr non gestisce correttamente il caso (in alcune circostanze)? , insieme a questa risposta: https://stackoverflow.com/a/8767815/1012053 .

Il problema è che FINDSTR non raccoglie i caratteri in base al loro valore del codice byte (comunemente pensato come codice ASCII, ma ASCII è definito solo da 0x00 - 0x7F). La maggior parte delle implementazioni regex tratterebbe [AZ] come tutte le lettere maiuscole inglesi maiuscole. Ma FINDSTR utilizza una sequenza di confronto che corrisponde approssimativamente a come funziona SORT. Quindi [AZ] include l'alfabeto inglese completo, sia maiuscolo che minuscolo (tranne "a"), nonché caratteri alfa non inglesi con segni diacritici.

Di seguito è riportato un elenco completo di tutti i caratteri supportati da FINDSTR, ordinati nella sequenza di confronto utilizzata da FINDSTR per stabilire intervalli di classi di caratteri regex. I caratteri sono rappresentati come valore decimale del codice byte. Credo che la sequenza delle regole di confronto abbia più senso se i personaggi vengono visualizzati utilizzando la tabella codici 437. Nota: questo elenco è stato compilato su una macchina americana. Non so quale impatto potrebbero avere altre lingue su 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

Limite di termini della classe di caratteri Regex e ERRORE
Non solo FINDSTR è limitato a un massimo di 15 termini di classe di caratteri all'interno di una regex, ma non riesce a gestire correttamente un tentativo di superare il limite. L'uso di 16 o più termini della classe di caratteri provoca un pop-up interattivo di Windows che indica "L'utilità Trova stringa (QGREP) ha riscontrato un problema e deve essere chiusa. Siamo spiacenti per l'inconveniente." Il testo del messaggio varia leggermente a seconda della versione di Windows. Ecco un esempio di FINDSTR 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 errore è stato segnalato dall'utente Judago DosTips qui . È stato confermato su XP, Vista e Windows 7.

Le ricerche Regex falliscono (e possono bloccarsi 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 in un intervallo di classi di caratteri. Ricorda che gli intervalli di classi di caratteri FINDSTR non raccolgono caratteri in base al valore del codice byte. Il personaggio <0xFF>appare relativamente presto nella sequenza di confronto tra i caratteri <space>e <tab>. Quindi qualsiasi intervallo di classi di caratteri che include entrambi <space>e <tab>fallirà.

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

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

Bug Regex: .e [^anySet]può corrispondere a End-Of-File
Il .meta-carattere regex deve corrispondere solo a qualsiasi carattere diverso da <CR>o <LF>. Esiste un bug che gli consente di abbinare l'End-Of-File se l'ultima riga nel file non è terminata da <CR>o <LF>. Tuttavia, .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 errore è stato confermato su XP e Win7.

Lo stesso sembra essere vero per i set di caratteri negativi. Qualcosa del genere [^abc]corrisponderà a End-Of-File. Set di caratteri positivi come [abc]sembrano funzionare bene. Ho provato questo solo su Win7.


1
findstr ha anche problemi con file di grandi dimensioni. File> 2 GB possono causare l'arresto di findstr. Non succede sempre. Nel confermare il bug ho cercato un file di 2,3 GB che non si bloccava. Si blocca anche se si cerca un solo file. Soluzione è inviare l'output di typein findstr.
Disilluso il

Probabilmente vale anche la pena menzionare esplicitamente che findstrsupporta più /c:stringhe di ricerca. So che le tue risposte lo dimostrano. Ma è qualcosa che non è documentato; e sono stato piuttosto sorpreso di apprendere la funzionalità dopo aver usato findstrsenza di essa per alcuni anni.
Disilluso il

@CraigYoung - Hai ragione sulle fonti della stringa di ricerca. Ho modificato la mia risposta, grazie.
dbenham,

1
Su ulteriori indagini, sembra una variazione sul LFproblema documentato. Mi sono reso conto che il mio file di test non è finito LFperché l'ho usato copyin modalità append per crearlo. Ho inserito una sessione della riga di comando per dimostrare il problema in una risposta ( stackoverflow.com/a/22943056/224704 ). Si noti che l'input non viene reindirizzato e tuttavia la ricerca si blocca. Lo stesso identico comando di ricerca non si blocca con file più piccoli che allo stesso modo non finiscono LF.
Disilluso l'

1
Nuova scoperta (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 classi di personaggi) - ErrorLevel = -1073740791 (0xC0000409), di dialogo finestra di errore : Find String (QGREP) Utility has stopped working; dopo aver rimosso una classe o due meta-caratteri ( *\.), funziona ...
aschipfl

7

findstr a volte si blocca in modo imprevisto durante la ricerca di file di grandi dimensioni.

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

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

La seguente sessione della riga di comando (Windows 7) mostra come si findstrpuò bloccare durante la ricerca di 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 che tutte le righe sono terminate CRLF. L'unica anomalia è che il file è terminato a 0x1Acausa del modo in cui copyfunziona . Si noti tuttavia che questa anomalia non causa problemi su file "piccoli" .

Con ulteriori test ho confermato quanto segue:

  • L'uso copycon l' /bopzione per i file binari impedisce l'aggiunta del 0x1Acarattere e findstrnon si blocca sul file da 3 GB.
  • La chiusura del file da 3 GB con un carattere diverso provoca anche un findstrblocco.
  • Il 0x1Apersonaggio non causa alcun problema su un file "piccolo". (Allo stesso modo per altri caratteri finali.)
  • L'aggiunta CRLFdopo 0x1Arisolve il problema. ( LFda solo probabilmente basterebbe.)
  • Utilizzare typeper reindirizzare il file findstrfunziona senza appenderlo. (Ciò potrebbe essere dovuto a un effetto collaterale di uno typeo |che inserisce un fine linea aggiuntivo.)
  • L'uso dell'input reindirizzato <causa anche il findstrblocco. Ma questo è previsto; come spiegato nel post di dbenham : "l'input reindirizzato deve terminare con LF" .

1
+1, sono in grado di confermare il problema sulla mia macchina Win7. Un file di dimensioni esattamente pari a 2GiB era sospeso quando l'ultimo carattere non lo era <LF>. Un file di due byte più piccolo non si è bloccato. Molto cattivo!
dbenham,

6

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 fino a quando i comandi nel blocco sono attivi, quindi i comandi possono spostare il puntatore dei file reindirizzati. Entrambi i comandi MORE e FIND 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

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

... produce lo stesso risultato di questo:

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

FINDSTR è diverso; essa non si muove 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

Possiamo fare buon uso di questa funzione 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 segnalato per la prima volta da Jeb in questo post .


EDIT 2018-08-18 : Nuovo bug FINDSTR segnalato

Il comando FINDSTR presenta 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 colori, vedere 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 viene 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 COLOR per ripristinare i colori di primo piano e di sfondo dell'intero schermo. Tuttavia, quando il testo è "invisibile", è possibile eseguire un comando SET / P, quindi tutti i caratteri immessi non verranno visualizzati sullo schermo. Questo comportamento può essere utilizzato per inserire 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%"

2

Vorrei segnalare un bug relativo alla sezione Origine dei dati da cercare nella prima risposta quando si utilizza en dash (-) o em dash (-) all'interno del nome file.

Più specificamente, se stai per utilizzare la prima opzione - nomi file specificati come argomenti , il file non verrà trovato. Non appena si utilizza l'opzione 2 - stdin tramite reindirizzamento o 3 - flusso di dati da una pipe , 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

stamperà:

Nome file con trattino:

  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 flusso di dati da una pipe
    sono il file con un trattino.

Nome file con trattino:

  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 flusso di dati da una pipe
    sono il file con un trattino.

Spero che sia d'aiuto.

M.


1
Ciao matro, anche se i tuoi commenti possono essere corretti, non sono sicuro che non rispondano alla domanda reale.
Wai Ha Lee,

Credo che questo sia un problema unicode, che FINDSTR non supporta. Il reindirizzamento CMD.EXE può aprire correttamente un nome file con unicode, così come il comando TYPE. Ma da qualche parte lungo la linea, FINDSTR converte sia il trattino sia il trattino in un trattino normale, e ovviamente il sistema operativo non riesce a trovare quel nome. Se si crea un altro file sostituendo un trattino per il trattino e / o il trattino, allora FINDSTR cercherà il file trattino se fornito con un nome contenente il trattino o il trattino.
dbenham,

Classificherei questo problema come una limitazione piuttosto che un bug.
dbenham,

In realtà, questo non è un problema unicode in quanto è esteso ASCII. Ho già documentato questo problema nella mia risposta originale sotto l'intestazione Limiti di carattere per i parametri della riga di comando - Trasformazione ASCII estesa . FINDSTR trasforma un numero di codici ASCII estesi in ASCII reali "correlati", inclusi en-dash ed em-dash.
dbenham,

1

Il findstrcomando imposta ErrorLevel(o il codice di uscita) su uno dei seguenti valori, dato che non ci sono opzioni non valide o incompatibili e nessuna stringa di ricerca supera il limite di lunghezza applicabile:

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

Si considera che una riga contenga una corrispondenza quando:

  • non /Vviene fornita alcuna opzione e l'espressione di ricerca si verifica almeno una volta;
  • /Vviene data l' opzione e non si verifica l'espressione di ricerca;

Ciò significa che l' /Vopzione modifica anche il reso ErrorLevel, ma non lo ripristina!

Ad esempio, quando avete un file test.txtcon due linee, una delle quali contiene la stringa text, ma l'altro non lo fa, sia findstr "text" "test.txt"e findstr /V "text" "test.txt"restituiscono un ErrorLeveldi 0.

Fondamentalmente puoi dire: se findstrrestituisce almeno una riga, ErrorLevelè impostato su 0, altrimenti su 1.

Si noti che l' /Mopzione non influisce sul ErrorLevelvalore, ma modifica semplicemente l'output.

(Solo per completezza: il findcomando si comporta esattamente allo stesso modo rispetto /Vall'opzione e ErrorLevel; l' /Copzione non ha effetto ErrorLevel.)


1

FINDSTR ha un bug di colore che ho descritto e risolto su /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Per riassumere quel thread, il bug è che se l'input viene reindirizzato a FINDSTR all'interno di un blocco di codice tra parentesi, i colorcode in linea ANSI escape smettono di funzionare nei comandi eseguiti in seguito. Un esempio di codici colore incorporati è: echo %magenta%Alert: Something bad happened%yellow%(dove magenta e giallo sono varianti definite precedentemente nel file .bat come i corrispondenti codici colore di escape ANSI).

La mia soluzione iniziale era quella di chiamare un sottoprogramma do-nothing dopo il FINDSTR. In qualche modo la chiamata o il ritorno "ripristinano" tutto ciò che deve essere ripristinato.

Successivamente ho scoperto un'altra soluzione che presumibilmente è più efficiente: posizionare la frase FINDSTR tra parentesi, come nell'esempio seguente: echo success | ( FINDSTR /R success ) Posizionare la frase FINDSTR in un blocco di codice nidificato sembra isolare il bug colorcode di FINDSTR in modo che non influisca su ciò che è al di fuori del nidificato bloccare. Forse questa tecnica risolverà anche altri effetti collaterali FINDSTR indesiderati .


Grande scoperta. Ma le tue regole possono essere semplificate (almeno sul mio computer Windows 10 aziendale). FINDSTR impedisce a tutte le sequenze di escape della console di funzionare per i comandi successivi all'interno dello stesso blocco comandi. Non importa se FINDSTR legge una pipe, un input reindirizzato o un file. L'errore della sequenza di escape non è limitato ai codici colore. Un blocco di comandi è un insieme di comandi tra parentesi e / o comandi concatenati tramite &, && o ||
dbenham,

@dbenham: bella generalizzazione del problema. Sai se la mia soluzione - annidare la frase FINDSTR tra parentesi - funziona anche nel caso generale? E sai se la mia soluzione ha effetti collaterali indesiderati?
Dolores Stevens,

Non ho fatto alcun test esaustivo, ma sì, le parentesi nidificate sembrano essere una soluzione generale e non riesco a pensare a possibili effetti collaterali indesiderati.
dbenham,

-1

/ D suggerimento per più directory: metti il ​​tuo elenco di directory prima della stringa di ricerca. Questi funzionano tutti:

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 la directory con \. Circondare il percorso con "è facoltativo se non ci sono spazi nei nomi delle directory. Il finale \è facoltativo. L'output della posizione includerà qualunque percorso tu gli dia. Funzionerà con o senza circondare l'elenco di directory con ".


Non vedo nulla di non documentato qui. L'opzione / D è descritta nella guida integrata. Questa non è una domanda per suggerimenti generali su come usare FINDSTR. È strettamente destinato a elencare funzionalità, limitazioni e / o bug non documentati.
dbenham,

1
@dbenham true non è veramente privo di documenti, ma ho scoperto che dovevo cercare con findstr i risultati desiderati e condividere ciò che trovavo funzionasse DID in modo che la gente non perdesse tempo a sperimentare comandi che NON funzionano. hth (sono triste che non ti piaccia il mio contributo - era destinato solo a essere costruttivo)
gordon

IMHO l'opzione / D è chiaramente descritta nella guida integrata: /D:dirlist Search a semicolon-delimited list of directoriesed è posizionata prima della stringa di ricerca, quindi non capisco cosa sia esattamente ciò che "hai trovato" sull'opzione / D (e quali sono i "comandi che NON lavorare ") ...
Aacini,

@Aacini in molte lingue, l'ordine degli attributi non ha importanza. Capisco prima la documentazione per gli findstrelenchi / D. Sì, non ho alcun argomento con la funzione che viene documentata, semplicemente non è documentata sul gotcha che conta l'ordine degli attributi. Faccio pochissimo lavoro a linea di comando, quindi quando stavo cobbellendo un comando, non sapendo che l'ordine faceva la differenza, stavo solo aggiungendo gli attributi man mano che li raggiungevo (e in ordine alfabetico, C precede D). Mi stavo davvero frustrando e ho condiviso la mia esperienza "trovata" per chiunque non lavori molto con la riga di comando.
Gordon,

1
L'ordine degli attributi opzionali di solito non ha importanza. La findstrdocumentazione specifica che la stringsparte NON è facoltativa e che è necessario posizionarla dopo gli attributi opzionali e prima dell'elenco dei nomi file facoltativi . Se "il tuo trovato" è che l'uso di un comando senza seguire il suo formato di utilizzo causa un errore, tale punto è ben documentato. Vedi Sintassi del comando : "La sintassi appare nell'ordine in cui è necessario digitare un comando e tutti i parametri che lo seguono"
Aacini
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.