Quais são os resources e limitações não documentados do comando Windows FINDSTR?

O comando Windows FINDSTR está horrivelmente documentado. Existe uma ajuda básica de linha de comando disponível através de FINDSTR /? , ou HELP FINDSTR , mas é totalmente inadequado. Há um pouco mais de documentação on-line em http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/findstr.mspx?mfr=true .

Existem muitos resources e limitações do FINDSTR que nem sequer são mencionados na documentação. Nem poderiam ser antecipados sem conhecimento prévio e / ou experimentação cuidadosa.

Então a questão é – Quais são as características e limitações não documentadas do FINDSTR?

O objective desta pergunta é fornecer um repository de um dos muitos resources não documentados para que:

A) Os desenvolvedores podem aproveitar ao máximo os resources que estão lá.

B) Os desenvolvedores não perdem seu tempo imaginando por que algo não funciona quando parece que deveria.

Por favor, certifique-se de conhecer a documentação existente antes de responder. Se a informação é coberta pela AJUDA, então ela não pertence aqui.

Nem é este um lugar para mostrar usos interessantes de FINDSTR. Se uma pessoa lógica puder prever o comportamento de um uso específico de FINDSTR com base na documentação, ela não pertence aqui.

Na mesma linha, se uma pessoa lógica puder antecipar o comportamento de um uso específico com base nas informações contidas em quaisquer respostas existentes, então, novamente, não pertence aqui.

Prefácio
Muitas das informações nesta resposta foram coletadas com base em experimentos executados em uma máquina Vista. A menos que seja explicitamente declarado o contrário, não confirmei se as informações se aplicam a outras versões do Windows.

Saída FINDSTR
A documentação nunca se incomoda em explicar a saída de FINDSTR. Alude ao fato de que as linhas correspondentes são impressas, mas nada mais.

O formato da saída de linha correspondente é o seguinte:

nome do arquivo: lineNumber: lineOffset: text

Onde

fileName: = O nome do arquivo que contém a linha correspondente. O nome do arquivo não será impresso se a solicitação for explicitamente para um único arquivo ou se a pesquisa de input canalizada ou de input redirecionada. Quando impresso, o nome do arquivo sempre includeá qualquer informação de caminho fornecida. Informações de caminho adicionais serão adicionadas se a opção /S for usada. O caminho impresso é sempre relativo ao caminho fornecido ou relativo ao diretório atual, se nenhum for fornecido.

Nota – O prefixo do nome do arquivo pode ser evitado ao pesquisar vários arquivos usando os curingas não padrão (e mal documentados) < e > . As regras exatas de como esses curingas funcionam podem ser encontradas aqui . Finalmente, você pode ver este exemplo de como os curingas não padrão funcionam com FINDSTR .

lineNumber: = O número da linha da linha correspondente representada como um valor decimal com 1 representando a 1ª linha da input. Somente impresso se a opção /N for especificada.

lineOffset: = O deslocamento de byte decimal do início da linha correspondente, com 0 representando o primeiro caractere da 1ª linha. Somente impresso se a opção /O for especificada. Este não é o deslocamento da partida dentro da linha. É o número de bytes desde o início do arquivo até o começo da linha.

text = A representação binária da linha correspondente, incluindo qualquer e / ou . Nada é deixado de fora da saída binária, de modo que este exemplo que corresponde a todas as linhas produzirá uma cópia binária exata do arquivo original.

 FINDSTR "^" FILE >FILE_COPY 

A maioria dos caracteres de controle e muitos caracteres ASCII estendidos são exibidos como pontos no XP
FINDSTR no XP exibe a maioria dos caracteres de controle não imprimíveis de linhas correspondentes como pontos (pontos) na canvas. Os seguintes caracteres de controle são exceções; eles são exibidos como: guia 0x09, alimentação de linha 0x0A, guia vertical 0x0B, alimentação de formulário 0x0C, devolução de carro 0x0D.

O XP FINDSTR também converte um número de caracteres ASCII estendidos em pontos também. Os caracteres ASCII estendidos exibidos como pontos no XP são os mesmos que são transformados quando fornecidos na linha de comando. Consulte a seção "Limites de caracteres para parâmetros de linha de comando - Transformação ASCII estendida" , mais adiante neste post

Caracteres de controle e ASCII estendido não são convertidos em pontos no XP se a saída for canalizada, redirecionada para um arquivo ou dentro de uma cláusula FOR IN ().

O Vista e o Windows 7 sempre exibem todos os caracteres como eles mesmos, nunca como pontos.

Códigos de retorno (ERRORLEVEL)

  • 0 (sucesso)
    • A correspondência foi encontrada em pelo menos uma linha de pelo menos um arquivo.
  • 1 (falha)
    • Nenhuma correspondência foi encontrada em qualquer linha de qualquer arquivo.
    • Cor inválida especificada pela opção /A:xx
  • 2 (erro)
    • Opções incompatíveis /L e /R especificados
    • Argumento ausente após /A: /F: /C: /D: ou /G:
    • Arquivo especificado por /F:file ou /G:file não encontrado
  • 255 (erro)
    • Muitos termos de class de caractere de expressão regular
      veja o limite de termos da class de caracteres Regex e o BUG na parte 2 da resposta

Fonte de dados a pesquisar (Atualizado com base em testes com o Windows 7)
O Findstr pode pesquisar dados de apenas uma das seguintes fonts:

  • nomes de arquivos especificados como argumentos e / ou usando a opção /F:file .

  • stdin via redirecionamento findstr "searchString"

  • stream de dados de um type file | findstr "searchString" pipe type file | findstr "searchString" type file | findstr "searchString"

Argumentos / opções têm precedência sobre o redirecionamento, que tem precedência sobre os dados canalizados.

Argumentos de nome de arquivo e /F:file podem ser combinados. Vários argumentos de nome de arquivo podem ser usados. Se várias opções de /F:file forem especificadas, somente a última será usada. As cartas curinga são permitidas nos argumentos do nome do arquivo, mas não no arquivo apontado por /F:file .

Fonte de seqüências de pesquisa (atualizadas com base em testes com o Windows 7)
As opções /G:file e /C:string podem ser combinadas. Várias /C:string opções de /C:string podem ser especificadas. Se várias opções de /G:file forem especificadas, somente a última será usada. Se /G:file ou /C:string for usado, todos os argumentos não opcionais serão considerados arquivos a serem pesquisados. Se nem o /G:file nor /C:string for usado, o primeiro argumento não-opcional será tratado como uma lista delimitada por espaço dos termos de pesquisa.

Nomes de arquivos não devem ser citados dentro do arquivo ao usar a opção /F:FILE .
Nomes de arquivos podem conter espaços e outros caracteres especiais. A maioria dos comandos exige que esses nomes de arquivos sejam citados. Mas a opção FINDSTR /F:files.txt requer que os nomes dos arquivos dentro dos arquivos.txt NÃO sejam citados. O arquivo não será encontrado se o nome estiver entre aspas.

BUG - nomes de arquivos curtos 8.3 podem quebrar as opções /D e /S
Como com todos os comandos do Windows, o FINDSTR tentará corresponder tanto o nome longo quanto o nome 8.3 curto ao procurar por arquivos para procurar. Suponha que a pasta atual contenha os seguintes arquivos não vazios:

 b1.txt b.txt2 c.txt 

O seguinte comando irá encontrar com sucesso todos os 3 arquivos:

 findstr /m "^" *.txt 

b.txt2 corresponde porque o nome abreviado correspondente B9F64~1.TXT corresponde. Isso é consistente com o comportamento de todos os outros comandos do Windows.

Mas um bug com as opções /D e /S faz com que os seguintes comandos só encontrem b1.txt

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

O bug impede que b.txt2 seja encontrado, assim como todos os nomes de arquivo que ordenam depois de b.txt2 no mesmo diretório. Arquivos adicionais que ordenam antes, como a.txt , são encontrados. Arquivos adicionais que são classificados posteriormente, como o d.txt , são perdidos quando o bug é acionado.

Cada diretório pesquisado é tratado de forma independente. Por exemplo, a opção /S começaria com êxito a pesquisa em uma pasta filho depois de falhar ao localizar arquivos no pai, mas uma vez que o bug faz com que um nome de arquivo curto seja perdido no filho, todos os arquivos subseqüentes nessa pasta também ser esquecido.

Os comandos funcionam livres de bugs se os mesmos nomes de arquivos forem criados em uma máquina com geração de nome NTFS 8.3 desativada. É claro que o b.txt2 não seria encontrado, mas o c.txt seria encontrado corretamente.

Nem todos os nomes abreviados acionam o bug. Todas as ocorrências de comportamento com bug que tenho visto envolvem uma extensão que é maior que 3 caracteres com um nome 8.3 curto que começa igual a um nome normal que não requer um nome 8.3.

O bug foi confirmado no XP, Vista e Windows 7.

Caracteres não imprimíveis e a opção /P
A opção /P faz com que FINDSTR pule qualquer arquivo que contenha qualquer um dos seguintes códigos de bytes decimais:
0-7, 14-25, 27-31.

Em outras palavras, a opção /P irá ignorar apenas arquivos que contenham caracteres de controle não imprimíveis. Caracteres de controle são códigos menores ou iguais a 31 (0x1F). FINDSTR trata os seguintes caracteres de controle como imprimíveis:

  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) 

Todos os outros caracteres de controle são tratados como não imprimíveis, cuja presença faz com que a opção /P ignore o arquivo.

A input canalizada e redirecionada pode ter anexado
Se a input for canalizada e o último caractere do stream não for , o FINDSTR appendá automaticamente à input. Isso foi confirmado no XP, Vista e Windows 7. (Eu costumava pensar que o pipe do Windows era responsável por modificar a input, mas descobri que o FINDSTR está realmente fazendo a modificação).

O mesmo vale para a input redirecionada no Vista. Se o último caractere de um arquivo usado como input redirecionada não for , então FINDSTR appendá automaticamente à input. No entanto, o XP e o Windows 7 não alteram a input redirecionada.

FINDSTR trava no XP e no Windows 7 se a input redirecionada não terminar com
Este é um "recurso" desagradável no XP e no Windows 7. Se o último caractere de um arquivo usado como input redirecionada não terminar com , o FINDSTR será interrompido indefinidamente assim que chegar ao final do arquivo redirecionado.

A última linha de dados Piped pode ser ignorada se consistir em um único caractere
Se a input é canalizada e a última linha consiste em um único caractere que não é seguido por , então FINDSTR ignora completamente a última linha.

Exemplo - O primeiro comando com um caractere único e nenhum não corresponde, mas o segundo comando com 2 caracteres funciona bem, assim como o terceiro comando que tem um caractere com nova linha de término.

 > set /p "=x"  set /p "=xx"  echo x| findstr "^" x 

Reportado pelo usuário do DosTips, Sponge Belly, no novo bug do findstr . Confirmado no XP, Windows 7 e Windows 8. Ainda não ouvi falar sobre o Vista. (Eu não tenho mais o Vista para testar).

Sintaxe da opção
As opções podem ser prefixadas com / ou - opções podem ser concatenadas após um único / ou - . No entanto, a lista de opções concatenadas pode conter no máximo uma opção multicharacter como OFF ou F: e a opção de vários caracteres deve ser a última opção na lista.

A seguir estão todas as formas equivalentes de expressar uma pesquisa regex insensível a maiúsculas e minúsculas para qualquer linha que contenha "hello" e "goodbye" em qualquer ordem

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

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

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

Pesquisar limites de comprimento de string
No Vista, o comprimento máximo permitido para uma única string de pesquisa é de 511 bytes. Se qualquer string de pesquisa exceder 511, o resultado será uma FINDSTR: Search string too long. erro com ERRORLEVEL 2.

Ao fazer uma pesquisa de expressão regular, o comprimento de seqüência de pesquisa máxima é 254. Uma expressão regular com comprimento entre 255 e 511 resultará em um FINDSTR: Out of memory Erro FINDSTR: Out of memory falta FINDSTR: Out of memory com ERRORLEVEL 2. Um comprimento de expressão regular> 511 resulta no FINDSTR: Search string too long. erro.

No Windows XP, o comprimento da string de pesquisa é aparentemente menor. Erro Findstr: "Cadeia de pesquisa longa demais": como extrair e combinar a substring no loop "for"? O limite de XP é 127 bytes para pesquisas literais e regex.

Limites de comprimento de linha
Arquivos especificados como um argumento de linha de comando ou através da opção / F: FILE não têm limite de comprimento de linha conhecido. As pesquisas foram executadas com êxito em um arquivo de 128 MB que não continha um único .

Dados canalizados e input redirecionada são limitados a 8191 bytes por linha. Esse limite é um "recurso" de FINDSTR. Não é inerente a pipes ou redirecionamento. FINDSTR usando stdin redirecionado ou input canalizada nunca corresponderá a nenhuma linha que seja> = 8k bytes. Linhas> = 8k geram uma mensagem de erro para stderr, mas ERRORLEVEL ainda é 0 se a cadeia de pesquisa for encontrada em pelo menos uma linha de pelo menos um arquivo.

Tipo de pesquisa padrão: expressão literal versus regular
/C:"string" - O padrão é o / L literal. Combinar explicitamente a opção / L com / C: "string" certamente funciona, mas é redundante.

"string argument" - O padrão depende do conteúdo da primeira string de pesquisa. (Lembre-se de que é usado para delimitar as sequências de pesquisa.) Se a primeira cadeia de pesquisa for uma expressão regular válida que contenha pelo menos um meta-caractere não-escapado, todas as sequências de pesquisa serão tratadas como expressões regulares. Caso contrário, todas as strings de pesquisa serão tratadas como literais. Por exemplo, "51.4 200" será tratado como duas expressões regulares porque a primeira cadeia contém um ponto não-escapado, enquanto "200 51.4" será tratado como duas literais porque a primeira cadeia não contém nenhum meta-caractere.

/G:file - O padrão depende do conteúdo da primeira linha não vazia no arquivo. Se a primeira cadeia de pesquisa for uma expressão regular válida que contenha pelo menos um meta-caractere não-escapado, todas as cadeias de pesquisa serão tratadas como expressões regulares. Caso contrário, todas as strings de pesquisa serão tratadas como literais.

Recomendação - Sempre especificar explicitamente a opção /L literal ou a opção de expressão regular /R ao usar "string argument" ou /G:file .

Erro - Especificando várias seqüências de pesquisa literal pode fornecer resultados não confiáveis

O seguinte exemplo FINDSTR simples não consegue encontrar uma correspondência, embora deva.

 echo ffffaaa|findstr /l "ffffaaa faffaffddd" 

Este bug foi confirmado no Windows Server 2003, Windows XP, Vista e Windows 7.

Com base em experimentos, o FINDSTR pode falhar se todas as condições a seguir forem atendidas:

  • A pesquisa está usando várias sequências de pesquisa literais
  • As cadeias de pesquisa são de diferentes comprimentos
  • Uma string de pesquisa curta tem alguma quantidade de sobreposição com uma string de pesquisa mais longa
  • A pesquisa é sensível a maiúsculas e minúsculas (opção não /I )

Em cada falha que tenho visto, é sempre uma das strings de pesquisa mais curtas que falha.

Para mais informações, consulte Por que este exemplo de FINDSTR com várias sequências de pesquisa literais encontra uma correspondência?

Citações e backslahses dentro de argumentos de linha de comando - Nota:
As informações nesta seção destacada não são 100% precisas. Depois de escrever esta seção, o usuário MC ND me indicou uma referência que documenta como a biblioteca Microsoft C / C ++ analisa os parâmetros . É terrivelmente complicado, mas parece prever com precisão as regras de barra invertida e cotação para argumentos de linha de comando FINDSTR. Eu recomendo que você use as informações destacadas abaixo como um guia, mas se você quiser informações mais precisas, consulte o link.

Escape de Citação dentro de seqüências de caracteres da linha de comando
Aspas dentro de seqüências de caracteres de pesquisa de linha de comando devem ser escapadas com barra invertida como \" . Isso é verdadeiro para seqüências de caracteres de pesquisa literal e regex. Essas informações foram confirmadas no XP, Vista e Windows 7.

Nota: A citação também pode precisar de escape para o analisador CMD.EXE, mas isso não tem nada a ver com FINDSTR. Por exemplo, para procurar uma cotação única, você poderia usar:

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

Escapando a barra invertida dentro das seqüências de caracteres de pesquisa literal da linha de comando
Barra invertida em uma string de pesquisa literal normalmente pode ser representada como \ ou como \\ . Eles são tipicamente equivalentes. (Pode haver casos incomuns no Vista em que a barra invertida deve sempre ser escapada, mas eu não tenho mais uma máquina do Vista para testar) .

Mas existem alguns casos especiais:

Ao procurar por barras invertidas consecutivas, todas, exceto as últimas, devem ser escapadas. A última barra invertida pode ser opcionalmente escapada.

  • \\ pode ser codificado como \\\ ou \\\\
  • \\\ pode ser codificado como \\\\\ ou \\\\\\

Procurando por uma ou mais barras invertidas antes que uma citação seja bizarra. A lógica sugeriria que a citação deve ser escapada, e cada uma das barras invertidas principais precisaria ser escapada, mas isso não funciona! Em vez disso, cada uma das barras invertidas deve ter escapado em dobro e a cotação é normalmente escapada:

  • \" deve ser codificado como \\\\\"
  • \\" deve ser codificado como \\\\\\\\\"

Como observado anteriormente, uma ou mais citações de escape também podem exigir escape com ^ para o analisador CMD

As informações desta seção foram confirmadas no XP e no Windows 7.

Escapando barra invertida dentro de seqüências de caracteres de pesquisa de regex de linha de comando

  • Somente para o Vista: a barra invertida em uma expressão regular deve ter o dobro de escape, como \\\\ , ou então, um único escape dentro de uma class de caracteres, como [\\]

  • XP e Windows 7: A barra invertida em um regex sempre pode ser representada como [\\] . Normalmente pode ser representado como \\ . Mas isso nunca funciona se a barra invertida precede uma cotação de escape.

    Uma ou mais barras invertidas antes de uma citação de escape deve ser duplicada ou codificada como [\\]

    • \" pode ser codificado como \\\\\" ou [\\]\"
    • \\" pode ser codificado como \\\\\\\\\" ou [\\][\\]\" ou \\[\\]\"

Escape de citações e barra invertida em / G: cadeias de caracteres literais FILE
Aspas e barras invertidas independentes em um arquivo de string de pesquisa literal especificado por / G: file não precisam ter escape, mas podem ser.

" e \" são equivalentes.

\ e \\ são equivalentes.

Se a intenção for localizar \\, então, pelo menos, a barra invertida inicial deve ser escapada. Tanto \\\ e \\\\ funcionam.

Se a intenção é encontrar \ ", então, pelo menos, a barra invertida de início deve ser escapada. Tanto \\" como \\\" funcionam.

Escape de citações e barras invertidas em / G: cadeias de caracteres de pesquisa de expressões regulares FILE
Esse é o único caso em que as seqüências de escape funcionam conforme o esperado com base na documentação. Citação não é um metacaractere de regex, portanto, não precisa ser escapado (mas pode ser). Barra invertida é um metacaractere de expressão regular, portanto deve ser escapado.

Limites de caracteres para parâmetros de linha de comando - Transformação ASCII estendida
O caractere nulo (0x00) não pode aparecer em nenhuma seqüência de caracteres na linha de comando. Qualquer outro caractere de byte único pode aparecer na string (0x01 - 0xFF). No entanto, FINDSTR converte muitos caracteres ASCII estendidos que ele encontra dentro de parâmetros de linha de comando em outros caracteres. Isso tem um grande impacto de duas maneiras:

1) Muitos caracteres ASCII estendidos não corresponderão a eles mesmos se usados ​​como uma string de pesquisa na linha de comando. Essa limitação é a mesma para pesquisas literais e regex. Se uma seqüência de pesquisa deve conter ASCII estendido, a opção /G:FILE deve ser usada em vez disso.

2) FINDSTR pode falhar em encontrar um arquivo se o nome contiver caracteres ASCII estendidos e o nome do arquivo for especificado na linha de comando. Se um arquivo a ser pesquisado contiver ASCII estendido no nome, a opção /F:FILE deve ser usada no lugar.

Aqui está uma lista completa de transformações de caracteres ASCII estendidos que FINDSTR executa em cadeias de linha de comando. Cada caractere é representado como o valor do código de bytes decimais. O primeiro código representa o caractere fornecido na linha de comando e o segundo código representa o caractere no qual ele é transformado. Nota - esta lista foi compilada em uma máquina dos EUA. Não sei o impacto que outras linguagens podem ter nessa lista.

 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 

Qualquer caractere> 0 que não esteja na lista acima é tratado como ele mesmo, incluindo e < LF> . A maneira mais fácil de include caracteres ímpares como e é inseri-los em uma variável de ambiente e usar a expansão atrasada dentro do argumento da linha de comando.

Limites de caracteres para strings encontradas em arquivos especificados pelas opções / G: FILE e / F: FILE
O caractere nul (0x00) pode aparecer no arquivo, mas funciona como o terminador de cadeia C. Qualquer caractere após um caractere nulo é tratado como uma string diferente, como se estivesse em outra linha.

Os caracteres e são tratados como terminadores de linha que terminam uma cadeia e não são incluídos na cadeia.

Todos os outros caracteres de byte único são incluídos perfeitamente dentro de uma string.

Procurando arquivos Unicode
FINDSTR não pode pesquisar corretamente a maioria dos Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) porque ele não pode procurar por bytes nulos e Unicode normalmente contém muitos bytes nulos.

No entanto, o comando TYPE converte UTF-16LE com BOM em um conjunto de caracteres de byte único, portanto, um comando como o seguinte funcionará com UTF-16LE com BOM.

 type unicode.txt|findstr "search" 

Observe que os pontos de código Unicode que não são suportados por sua página de código ativa serão convertidos em ? personagens.

É possível pesquisar o UTF-8 desde que a sua cadeia de pesquisa contenha apenas ASCII. No entanto, a saída do console de qualquer caractere UTF-8 de vários bytes não estará correta. Mas se você redirect a saída para um arquivo, o resultado será codificado corretamente pelo UTF-8. Observe que, se o arquivo UTF-8 contiver uma lista técnica, a lista técnica será considerada como parte da primeira linha, o que poderia prejudicar uma pesquisa que corresponda ao início de uma linha.

É possível pesquisar caracteres UTF-8 de vários bytes se você colocar sua sequência de pesquisa em um arquivo de pesquisa codificado em UTF-8 (sem BOM) e usar a opção / G.

Fim da linha
FINDSTR quebra as linhas imediatamente após cada . A presença ou ausência de não afeta as quebras de linha.

Pesquisando através de quebras de linha
Como esperado, o . O metacaractere regex não coincide com ou . Mas é possível pesquisar em uma quebra de linha usando uma string de pesquisa de linha de comando. Os caracteres e devem ser correspondidos explicitamente. Se uma correspondência de várias linhas for encontrada, somente a primeira linha da partida será impressa. FINDSTR, em seguida, dobra de volta para a segunda linha na fonte e começa a busca mais uma vez - uma espécie de "olhar para frente" tipo de recurso.

Suponha que o TEXT.TXT tenha este conteúdo (pode ser o estilo Unix ou Windows)

 A A A B A A 

Então esse roteiro

 @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á esses resultados

 1:A 2:A 5:A 

A pesquisa entre as quebras de linha usando a opção / G: FILE é imprecisa porque a única maneira de corresponder a ou é por meio de uma expressão de intervalo de class de caracteres regex que imprime os caracteres EOL.

  • [-<0x0B>] corresponde a , mas também corresponde a e <0x0B>

  • [<0x0C>-!] , mas também corresponde a <0x0C> e!

    Nota - o acima são representações simbólicas do stream de byte regex desde que eu não posso representar graficamente os caracteres.

A resposta continuou na parte 2 abaixo ...

Resposta continuada da parte 1 acima – encontrei o limite de 30.000 caracteres 🙁

Suporte de Expressões Regulares Limitadas (regex)
O suporte FINDSTR para expressões regulares é extremamente limitado. Se não estiver na documentação de AJUDA, não será suportado.

Além disso, as expressões regex que são suportadas são implementadas de uma maneira completamente não padrão, de modo que os resultados podem ser diferentes, então seria esperado vindo de algo como grep ou perl.

Âncoras de posição da linha Regex ^ e $
^ coincide o início do stream de input, bem como qualquer posição imediatamente após um . Como FINDSTR também quebra as linhas após , uma regex simples de “^” sempre corresponderá a todas as linhas dentro de um arquivo, mesmo que seja um arquivo binário.

$ corresponde a qualquer posição imediatamente anterior a um . Isso significa que uma string de pesquisa regex contendo $ nunca corresponderá a nenhuma linha dentro de um arquivo de texto estilo Unix, nem corresponderá à última linha de um arquivo de texto do Windows se estiver faltando o marcador EOL de .

Nota – Como discutido anteriormente, a input canalizada e redirecionada para FINDSTR pode ter o anexado que não está na origem. Obviamente, isso pode afetar uma pesquisa de regex que usa $ .

Qualquer string de pesquisa com caracteres antes de ^ ou depois de $ sempre falhará ao encontrar uma correspondência.

Opções Posicionais / B / E / X
As opções posicionais funcionam da mesma forma que ^ e $ , exceto que elas também funcionam para sequências de pesquisa literais.

/ B funciona da mesma maneira que ^ no início de uma string de pesquisa regex.

/ E funciona da mesma forma que $ no final de uma string de pesquisa regex.

/ X funciona da mesma maneira que ter ambos ^ no início e $ no final de uma string de pesquisa regex.

Limite da palavra Regex
\< deve ser o primeiro termo no regex. O regex não corresponderá a nada se algum outro caractere o preceder. \< corresponde ao início da input, ao início de uma linha (a posição imediatamente após um ) ou à posição imediatamente após qualquer caractere "sem palavra". O próximo caractere não precisa ser um caractere de "palavra".

\> deve ser o último termo no regex. O regex não corresponderá a nada se algum outro caractere o seguir. \> corresponde ao final da input, à posição imediatamente anterior a um ou à posição imediatamente anterior a qualquer caractere "sem palavra". O personagem precedente não precisa ser um caractere de "palavra".

Aqui está uma lista completa de caracteres "não-palavra", representada como o código de bytes decimais. Nota - esta lista foi compilada em uma máquina dos EUA. Não sei o impacto que outras linguagens podem ter nessa 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 

Gamas de classs de caracteres Regex [xy]
Os intervalos de class de caracteres não funcionam conforme o esperado. Veja esta pergunta: Por que o findstr não manipula o caso adequadamente (em algumas circunstâncias)? , juntamente com esta resposta: https://stackoverflow.com/a/8767815/1012053 .

O problema é que FINDSTR não agrupa os caracteres pelo seu valor de código de byte (comumente considerado como o código ASCII, mas o ASCII é definido apenas de 0x00 - 0x7F). A maioria das implementações de regex trataria [AZ] como todas as letras maiúsculas em inglês. Mas o FINDSTR usa uma seqüência de intercalação que corresponde aproximadamente a como o SORT funciona. Portanto, [AZ] inclui o alfabeto completo em inglês, tanto maiúsculas e minúsculas (exceto "a"), como também caracteres alfabéticos não ingleses com diacríticos.

Abaixo está uma lista completa de todos os caracteres suportados pelo FINDSTR, classificados na seqüência de intercalação usada por FINDSTR para estabelecer intervalos de class de caracteres de expressão regular. Os caracteres são representados como seu valor de código de bytes decimais. Acredito que a seqüência de intercalação faz mais sentido se os caracteres forem visualizados usando a página de códigos 437. Nota - esta lista foi compilada em uma máquina americana. Não sei o impacto que outras linguagens podem ter nessa 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 de termo da class de caracteres Regex e BUG
Não só é FINDSTR limitado a um máximo de 15 termos de class de caracteres dentro de um regex, ele não consegue lidar adequadamente com uma tentativa de exceder o limite. O uso de 16 ou mais termos de class de caracteres resulta em um pop-up interativo do Windows informando que o utilitário "Find String (QGREP) encontrou um problema e precisa ser fechado. Pedimos desculpas pelo inconveniente". O texto da mensagem varia ligeiramente dependendo da versão do Windows. Aqui está um exemplo de um FINDSTR que irá falhar:

 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] 

Esse bug foi relatado pelo usuário da DosTips, Judago, aqui . Foi confirmado no XP, Vista e Windows 7.

Pesquisas Regex falhar (e pode travar indefinidamente) se eles incluem código de byte 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 and characters. So any character class range that includes both and 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 or . There is a bug that allows it to match the End-Of-File if the last line in the file is not terminated by or . However, the . will not match an empty file.

For example, a file named "test.txt" containing a single line of x , without terminating or , 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.

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  . 2014/04/08 04:28 PM  .. 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 " .

When several commands are enclosed in parentheses and there are redirected files to the whole block:

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

… then the files remains open as long as the commands in the block be active, so the commands may move the file pointer of the redirected files. Both MORE and FIND commands move the Stdin file pointer to the beginning of the file before process it, so the same file may be processed several times inside the block. For example, this code:

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

… produce the same result than this one:

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

Este código:

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

… produce the same result than this one:

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

FINDSTR is different; it does not move the Stdin file pointer from its current position. For example, this code insert a new line after a search line:

 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 

We may make good use of this feature with the aid of an auxiliary program that allow us to move the file pointer of a redirected file, as shown in this example .

This behavior was first reported by jeb at this post .


EDIT 2018-08-18 : New FINDSTR bug reported

The FINDSTR command have a strange bug that happen when this command is used to show characters in color AND the output of such a command is redirected to CON device. For details on how use FINDSTR command to show text in color, see this topic .

When the output of this form of FINDSTR command is redirected to CON, something strange happens after the text is output in the desired color: all the text after it is output as "invisible" characters, although a more precise description is that the text is output as black text over black background. The original text will appear if you use COLOR command to reset the foreground and background colors of the entire screen. However, when the text is "invisible" we could execute a SET /P command, so all characters entered will not appear on the screen. This behavior may be used to enter passwords.

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

I’d like to report a bug regarding the section Source of data to search in the first answer when using en dash (–) or em dash (—) within the filename.

More specifically, if you are about to use the first option – filenames specified as arguments , the file won’t be found. As soon as you use either option 2 – stdin via redirection or 3 – data stream from a pipe , findstr will find the file.

For example, this simple batch script:

 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 

will print:

Filename with en dash:

  1. As argument
    FINDSTR: Cannot open filename with - dash.txt

  2. As stdin via redirection
    I am the file with an en dash.

  3. As datastream from a pipe
    I am the file with an en dash.

Filename with em dash:

  1. As argument
    FINDSTR: Cannot open filename with - dash.txt

  2. As stdin via redirection
    I am the file with an em dash.

  3. As datastream from a pipe
    I am the file with an em dash.

Espero que ajude.

M.

/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 " .