[Batch-file] Quali sono le funzionalità non documentate e le limitazioni del comando FINDSTR di Windows?


Answers

Risposta continua dalla prima parte sopra - Ho incontrato il limite di risposta di 30.000 caratteri :-(

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

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

Ancore posizione Regex Line ^ e $
^ corrisponde all'inizio del flusso di input e qualsiasi posizione immediatamente successiva a <LF>. Poiché FINDSTR interrompe anche le linee dopo <LF>, una semplice espressione regolare di "^" corrisponderà sempre a tutte le righe all'interno 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 potrà mai corrispondere 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 di <CR> <LF>.

Nota - Come già discusso, l'input con pipe e reindirizzato su FINDSTR può avere <CR><LF> aggiunto che non si trova nella sorgente. Ovviamente questo può influire su una ricerca regex che utilizza $ .

Qualsiasi stringa di ricerca con caratteri prima di ^ o dopo $ fallirà sempre nel trovare una corrispondenza.

Opzioni di posizione / B / E / X
Le opzioni posizionali funzionano come ^ e $ , eccetto che funzionano anche per le stringhe di ricerca letterale.

/ B funziona come ^ all'inizio di una stringa di ricerca regolare.

/ E funziona come $ alla fine di una stringa di ricerca regex.

/ X funziona allo stesso modo di avere entrambi ^ all'inizio e $ alla fine di una stringa di ricerca regolare.

Confine della parola Regex
\< deve essere il primo termine nella regex. La regex non corrisponderà a nulla se altri caratteri lo precedono. \< corrisponde sia all'inizio dell'ingresso, all'inizio di una riga (la posizione immediatamente successiva a <LF>), o alla posizione immediatamente successiva a qualsiasi carattere di "non parola". Il prossimo personaggio non deve essere un personaggio "parola".

\> deve essere l'ultimo termine nella regex. L'espressione regolare non corrisponderà a nulla se altri caratteri lo seguiranno. \> corrisponde alla fine dell'input, alla posizione immediatamente precedente a <CR>, o alla posizione immediatamente precedente a qualsiasi carattere "non-word". Il personaggio precedente non deve essere un carattere "parola".

Ecco una lista completa di caratteri "non parole", rappresentati come codice decimale dei byte. Nota: questa lista è stata compilata su una macchina statunitense. Non so quale impatto potrebbero avere altre lingue in questa lista.

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 classe di caratteri Regex [xy]
Gli intervalli di classe dei 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 collaziona i caratteri con il loro valore di codice byte (comunemente pensato come il codice ASCII, ma ASCII è definito solo da 0x00 - 0x7F). La maggior parte delle implementazioni regex considerano [AZ] come maiuscole maiuscole 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 (eccetto per "a"), così come i 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 regolari. I caratteri sono rappresentati come il loro valore di codice byte decimale. Ritengo che la sequenza di confronto abbia più senso se i caratteri vengono visualizzati utilizzando la code page 437. Nota: questo elenco è stato compilato su una macchina statunitense. Non so quale impatto potrebbero avere altre lingue in questa lista.

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 dei termini della classe dei caratteri Regex e BUG
Non solo FINDSTR è limitato a un massimo di 15 termini di classe di caratteri all'interno di un'espressione regolare, ma non riesce a gestire correttamente un tentativo di superare il limite. L'utilizzo di 16 o più termini di classe del carattere genera un popup interattivo di Windows che indica che l' utilità "Trova stringa (QGREP) ha riscontrato un problema e deve essere chiusa. Ci scusiamo per l'inconveniente". Il testo del messaggio varia leggermente a seconda della versione di Windows. Here is one example of a FINDSTR that will fail:

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]

This bug was reported by DosTips user Judago here . It has been confirmed on XP, Vista, and Windows 7.

Regex searches fail (and may hang indefinitely) if they include byte code 0xFF (decimal 255)
Any regex search that includes byte code 0xFF (decimal 255) will fail. It fails if byte code 0xFF is included directly, or if it is implicitly included within a character class range. Remember that FINDSTR character class ranges do not collate characters based on the byte code value. Character <0xFF> appears relatively early in the collation sequence between the <space> and <tab> characters. So any character class range that includes both <space> and <tab> will fail.

The exact behavior changes slightly depending on the Windows version. Windows 7 hangs indefinitely if 0xFF is included. XP doesn't hang, but it always fails to find a match, and occasionally prints the following error message - "The process tried to write to a nonexistent pipe."

I no longer have access to a Vista machine, so I haven't been able to test on Vista.

Regex bug: . and [^anySet] can match End-Of-File
The regex . meta-character should only match any character other than <CR> or <LF> . There is a bug that allows it to match the End-Of-File if the last line in the file is not terminated by <CR> or <LF> . However, the . will not match an empty file.

For example, a file named "test.txt" containing a single line of x , without terminating <CR> or <LF> , will match the following:

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

This bug has been confirmed on XP and Win7.

The same seems to be true for negative character sets. Something like [^abc] will match End-Of-File. Positive character sets like [abc] seem to work fine. I have only tested this on Win7.

Question

Il comando FINDSTR di Windows è orribilmente documentato. C'è una guida di linea di comando molto semplice disponibile attraverso FINDSTR /? o HELP FINDSTR , ma è tristemente inadeguato. C'è un po 'più di documentazione online su http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/findstr.mspx?mfr=true .

Ci sono molte caratteristiche e limitazioni di FINDSTR che non sono nemmeno suggerite nella documentazione. Né potevano essere anticipati senza una conoscenza preliminare e / o un'attenta sperimentazione.

Quindi la domanda è: quali sono le caratteristiche e le limitazioni di FINDSTR non documentate?

Lo scopo di questa domanda è fornire un repository unico per le molte funzionalità non documentate in modo che:

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

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

Assicurati di conoscere la documentazione esistente prima di rispondere. Se l'informazione è coperta dall'aiuto, allora non appartiene a questo.

Né è questo un luogo per mostrare usi interessanti di FINDSTR. Se una persona logica può anticipare il comportamento di un particolare utilizzo di FINDSTR basato sulla documentazione, allora non appartiene a questo.

Sulla stessa falsariga, se una persona logica potrebbe anticipare il comportamento di un particolare utilizzo basato su informazioni contenute in qualsiasi risposta esistente, allora di nuovo, non appartiene a questo.




findstr sometimes hangs unexpectedly when searching large files.

I haven't confirmed the exact conditions or boundary sizes. I suspect any file larger 2GB may be at risk.

I have had mixed experiences with this, so it is more than just file size. This looks like it may be a variation on FINDSTR hangs on XP and Windows 7 if redirected input does not end with LF , but as demonstrated this particular problem manifests when input is not redirected.

The following command line session (Windows 7) demonstrates how findstr can hang when searching a 3GB file.

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>

Note, I've verified in a hex editor that all lines are terminated with CRLF . The only anomaly is that the file is terminated with 0x1A due to the way copy works . Note however, that this anomaly doesn't cause a problem on "small" files .

With additional testing I have confirmed the following:

  • Using copy with the /b option for binary files prevents the addition of the 0x1A character, and findstr doesn't hang on the 3GB file.
  • Terminating the 3GB file with a different character also causes a findstr to hang.
  • The 0x1A character doesn't cause any problems on a "small" file. (Similarly for other terminating characters.)
  • Adding CRLF after 0x1A resolves the problem. ( LF by itself would probably suffice.)
  • Using type to pipe the file into findstr works without hanging. (This might be due to a side effect of either type or | that inserts an additional End Of Line.)
  • Use redirected input < also causes findstr to hang. But this is expected; as explained in dbenham's post : "redirected input must end in LF " .



/D tip for multiple directories: put your directory list before the search string. These all work:

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

As expected, the path is relative to location if you don't start the directories with \ . Surrounding the path with " is optional if there are no spaces in the directory names. The ending \ is optional. The output of location will include whatever path you give it. It will work with or without surrounding the directory list with " .