¿Cuáles son las características y limitaciones no documentadas del comando FINDSTR de Windows?

188

El comando FINDSTR de Windows está horriblemente documentado. Hay ayuda de línea de comandos muy básica disponible a través de FINDSTR /?, o HELP FINDSTR, pero es lamentablemente inadecuada. Hay un poquito más de documentación en línea en https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

Hay muchas características y limitaciones de FINDSTR que ni siquiera se mencionan en la documentación. Tampoco podrían anticiparse sin conocimiento previo y / o experimentación cuidadosa.

Entonces la pregunta es: ¿cuáles son las características y limitaciones de FINDSTR no documentadas?

El propósito de esta pregunta es proporcionar un repositorio único de las muchas características no documentadas para que:

A) Los desarrolladores pueden aprovechar al máximo las características que están allí.

B) Los desarrolladores no pierden el tiempo preguntándose por qué algo no funciona cuando parece que debería funcionar.

Asegúrese de conocer la documentación existente antes de responder. Si la información está cubierta por la AYUDA, entonces no pertenece aquí.

Tampoco es este un lugar para mostrar usos interesantes de FINDSTR. Si una persona lógica podría anticipar el comportamiento de un uso particular de FINDSTR basado en la documentación, entonces no pertenece aquí.

En la misma línea, si una persona lógica pudiera anticipar el comportamiento de un uso particular basado en la información contenida en las respuestas existentes, entonces, nuevamente, no pertenece aquí.

dbenham
fuente
15
O, alternativamente, podría deshacerse de la utilidad MS indocumentada por completo e instalar / usar, grepque se entiende y documenta muy bien :-) Ver stackoverflow.com/questions/2635740/… por ejemplo.
paxdiablo
17
Por supuesto, si está en condiciones de utilizar algo que no sea FINDSTR, entonces es muy recomendable. Pero algunas personas se encuentran en entornos donde las utilidades de terceros están prohibidas.
dbenham
44
No se ofende. ¡Realmente consideré poner mi propio descargo de responsabilidad FINDSTR que fue similar a tu comentario! :)
dbenham
41
Estoy sorprendido y decepcionado de que alguien encuentre esta pregunta "No constructiva" y vote para cerrar. Se pensó mucho en la pregunta específicamente para evitar "opiniones, debates, argumentos, encuestas o discusiones extensas". La pregunta ha sido publicada durante 3.5 meses, y ninguno de los aspectos negativos citados ha ocurrido. La respuesta combinada está llena de hechos y requiere muchas horas de minuciosa investigación y experimentación.
dbenham
66
Algunos lectores pueden estar interesados ​​en el contexto histórico del comando findtr
Harry Johnston

Respuestas:

279

Prefacio
Gran parte de la información de esta respuesta se ha recopilado en base a experimentos realizados en una máquina Vista. A menos que se indique explícitamente lo contrario, no he confirmado si la información se aplica a otras versiones de Windows.

Salida FINDSTR
La documentación nunca se molesta en explicar la salida de FINDSTR. Alude al hecho de que se imprimen líneas coincidentes, pero nada más.

El formato de salida de línea coincidente es el siguiente:

filename: lineNumber: lineOffset: text

dónde

nombre del archivo: = El nombre del archivo que contiene la línea coincidente. El nombre del archivo no se imprime si la solicitud fue explícitamente para un solo archivo, o si se busca una entrada canalizada o una entrada redirigida. Cuando se imprime, el nombre del archivo siempre incluirá cualquier información de ruta proporcionada. Se agregará información de ruta adicional si /Sse utiliza la opción. La ruta impresa siempre es relativa a la ruta proporcionada, o relativa al directorio actual si no se proporciona ninguno.

Nota - El prefijo de nombre de archivo se puede evitar cuando se busca varios archivos mediante el uso de la no-estándar (y mal documentados) comodines < y >. Las reglas exactas sobre cómo funcionan estos comodines se pueden encontrar aquí . Finalmente, puede ver este ejemplo de cómo funcionan los comodines no estándar con FINDSTR .

lineNumber: = El número de línea de la línea coincidente representada como un valor decimal con 1 que representa la primera línea de la entrada. Solo se imprime si/Nse especifica la opción.

lineOffset: = El desplazamiento del byte decimal del inicio de la línea coincidente, donde 0 representa el primer carácter de la primera línea. Solo se imprime si/Ose especifica la opción. Este no esel desplazamiento de la coincidencia dentro de la línea. Es el número de bytes desde el comienzo del archivo hasta el comienzo de la línea.

text = La representación binaria de la línea coincidente, incluidos <CR> y / o <LF>. No queda nada fuera de la salida binaria, de modo que este ejemplo que coincida con todas las líneas producirá una copia binaria exacta del archivo original.

FINDSTR "^" FILE >FILE_COPY

La opción / A establece el color del fileName :, lineNumber :, y lineOffset: solo salida. El texto de la línea coincidente siempre sale con el color de la consola actual. La opción / A solo tiene efecto cuando la salida se muestra directamente en la consola. La opción / A no tiene efecto si la salida se redirige a un archivo o se canaliza. Consulte la edición de 2018-08-18 en la respuesta de Aacini para obtener una descripción del comportamiento defectuoso cuando la salida se redirige a CON.

La mayoría de los caracteres de control y muchos caracteres ASCII extendidos se muestran como puntos en XP
FINDSTR en XP muestra la mayoría de los caracteres de control no imprimibles de líneas coincidentes como puntos (puntos) en la pantalla. Los siguientes caracteres de control son excepciones; se muestran como ellos mismos: 0x09 Tabulación, 0x0A LineFeed, 0x0B Vertical Tab, 0x0C Form Feed, 0x0D Carriage Return.

XP FINDSTR también convierte una cantidad de caracteres ASCII extendidos en puntos también. Los caracteres ASCII extendidos que se muestran como puntos en XP son los mismos que se transforman cuando se proporcionan en la línea de comandos. Consulte la sección "Límites de caracteres para los parámetros de la línea de comandos: transformación ASCII extendida" , más adelante en esta publicación

Los caracteres de control y ASCII extendido no se convierten en puntos en XP si la salida se canaliza, se redirige a un archivo o dentro de una cláusula FOR IN ().

Vista y Windows 7 siempre muestran todos los caracteres como ellos mismos, nunca como puntos.

Códigos de retorno (ERRORLEVEL)

  • 0 (éxito)
    • Se encontró coincidencia en al menos una línea de al menos un archivo.
  • 1 (falla)
    • No se encontraron coincidencias en ninguna línea de ningún archivo.
    • Color no válido especificado por la /A:xxopción
  • 2 (error)
    • Opciones incompatibles /Ly /Rambas especificadas
    • Falta el argumento tras /A:, /F:, /C:, /D:, o/G:
    • Archivo especificado por /F:fileo /G:fileno encontrado
  • 255 (error)

Fuente de datos para buscar (actualizado en base a pruebas con Windows 7)
Findstr puede buscar datos de solo una de las siguientes fuentes:

  • nombres de archivo especificados como argumentos y / o utilizando la /F:fileopción

  • stdin a través de la redirección findstr "searchString" <file

  • flujo de datos desde una tubería type file | findstr "searchString"

Los argumentos / opciones tienen prioridad sobre la redirección, que tiene prioridad sobre los datos canalizados.

Argumentos de nombre de archivo y /F:filese pueden combinar. Se pueden usar múltiples argumentos de nombre de archivo. Si /F:filese especifican varias opciones, solo se usa la última. Los comodines están permitidos en los argumentos de nombre de archivo, pero no dentro del archivo señalado por /F:file.

Fuente de las cadenas de búsqueda (actualizado basado en pruebas con Windows 7)
Las opciones /G:filey /C:stringpueden combinarse. Se /C:stringpueden especificar múltiples opciones. Si /G:filese especifican varias opciones, solo se usa la última. Si se usa /G:fileo /C:string, se supone que todos los argumentos que no son opciones son archivos para buscar. Si no se utiliza ni /G:filetampoco /C:string, entonces el primer argumento sin opción se trata como una lista delimitada por espacios de términos de búsqueda.

Los nombres de archivo no se deben citar dentro del archivo cuando se usa la /F:FILEopción.
Los nombres de archivo pueden contener espacios y otros caracteres especiales. La mayoría de los comandos requieren que se citen dichos nombres de archivo. Pero la /F:files.txtopción FINDSTR requiere que los nombres de archivo dentro de files.txt NO se deben citar. El archivo no se encontrará si se cita el nombre.

ERROR: los nombres cortos de archivo 8.3 pueden romper las opciones /Dy/S
Al igual que con todos los comandos de Windows, FINDSTR intentará hacer coincidir tanto el nombre largo como el nombre corto 8.3 al buscar archivos para buscar. Suponga que la carpeta actual contiene los siguientes archivos no vacíos:

b1.txt
b.txt2
c.txt

El siguiente comando encontrará con éxito los 3 archivos:

findstr /m "^" *.txt

b.txt2coincide porque coincide el nombre corto correspondiente B9F64~1.TXT. Esto es coherente con el comportamiento de todos los demás comandos de Windows.

Pero un error con las opciones /Dy /Shace que los siguientes comandos solo encuentrenb1.txt

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

El error evita que b.txt2se encuentren, así como todos los nombres de archivo que se ordenan después b.txt2dentro del mismo directorio. Se encuentran archivos adicionales que se ordenan antes, como a.txt. Los archivos adicionales que se ordenan más tarde, como d.txt, se pierden una vez que se ha activado el error.

Cada directorio buscado se trata de forma independiente. Por ejemplo, la /Sopción comenzaría a buscar con éxito en una carpeta secundaria después de no encontrar archivos en el padre, pero una vez que el error hace que se pierda un nombre de archivo corto en el niño, también se perderán todos los archivos posteriores en esa carpeta secundaria. .

Los comandos funcionan sin errores si se crean los mismos nombres de archivo en una máquina que tiene la generación de nombres NTFS 8.3 deshabilitada. Por supuesto b.txt2, no se encontraría, pero c.txtse encontraría correctamente.

No todos los nombres cortos activan el error. Todas las instancias de comportamiento con errores que he visto involucran una extensión que tiene más de 3 caracteres con un nombre corto de 8.3 que comienza igual que un nombre normal que no requiere un nombre de 8.3.

El error ha sido confirmado en XP, Vista y Windows 7.

Caracteres no imprimibles y la /Popción
La /Popción hace que FINDSTR omita cualquier archivo que contenga cualquiera de los siguientes códigos de bytes decimales:
0-7, 14-25, 27-31.

Dicho de otra manera, la /Popción solo omitirá los archivos que contengan caracteres de control no imprimibles. Los caracteres de control son códigos menores o iguales a 31 (0x1F). FINDSTR trata los siguientes caracteres de control como imprimibles:

 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 los demás caracteres de control se tratan como no imprimibles, cuya presencia hace que la /Popción omita el archivo.

<CR><LF>
La entrada canalizada y redirigida puede haberse agregado Si la entrada está canalizada y el último carácter de la secuencia no <LF>, FINDSTR se agregará automáticamente <CR><LF>a la entrada. Esto se ha confirmado en XP, Vista y Windows 7. (Solía ​​pensar que la tubería de Windows era responsable de modificar la entrada, pero desde entonces descubrí que FINDSTR realmente está haciendo la modificación).

Lo mismo es cierto para la entrada redirigida en Vista. Si el último carácter de un archivo utilizado como entrada redirigida no lo es <LF>, FINDSTR se agregará automáticamente <CR><LF>a la entrada. Sin embargo, XP y Windows 7 no alteran la entrada redirigida.

FINDSTR se bloquea en XP y Windows 7 si la entrada redirigida no termina con<LF>
Esta es una "característica" desagradable en XP y Windows 7. Si el último carácter de un archivo utilizado como entrada redirigida no termina <LF>, FINDSTR se bloqueará indefinidamente una vez que llega al final del archivo redirigido.

La última línea de datos
canalizados puede ignorarse si consta de un solo carácter Si la entrada se canaliza y la última línea consta de un único carácter al que no sigue <LF>, FINDSTR ignora por completo la última línea.

Ejemplo: el primer comando con un solo carácter y ninguno <LF>no coincide, pero el segundo comando con 2 caracteres funciona bien, al igual que el tercer comando que tiene un carácter con nueva línea de terminación.

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

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

> echo x| findstr "^"
x

Reportado por el usuario de DosTips Sponge Belly en el nuevo error de findtr . Confirmado en XP, Windows 7 y Windows 8. Todavía no he oído hablar de Vista. (Ya no tengo Vista para probar).

Sintaxis de la opción Las
opciones se pueden prefijar con /o las - opciones se pueden concatenar después de una sola /o -. Sin embargo, la lista de opciones concatenadas puede contener como máximo una opción de caracteres múltiples como OFF o F :, y la opción de caracteres múltiples debe ser la última opción en la lista.

Las siguientes son formas equivalentes de expresar una búsqueda de expresiones regulares sin distinción entre mayúsculas y minúsculas para cualquier línea que contenga "hola" y "adiós" en cualquier orden

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

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

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

Límites de longitud de la cadena de búsqueda
En Vista, la longitud máxima permitida para una sola cadena de búsqueda es de 511 bytes. Si alguna cadena de búsqueda supera 511, el resultado es un FINDSTR: Search string too long.error con ERRORLEVEL 2.

Al realizar una búsqueda de expresión regular, la longitud máxima de la cadena de búsqueda es 254. Una expresión regular con una longitud entre 255 y 511 dará como resultado un FINDSTR: Out of memoryerror con ERRORLEVEL 2. Una longitud de expresión regular> 511 produce el FINDSTR: Search string too long.error.

En Windows XP, la longitud de la cadena de búsqueda es aparentemente más corta. Error Findstr: "Cadena de búsqueda demasiado larga": ¿Cómo extraer y hacer coincidir la subcadena en el bucle "for"? El límite de XP es de 127 bytes para búsquedas literales y expresiones regulares.

Límites de longitud de línea Los
archivos especificados como argumento de línea de comando o mediante la opción / F: FILE no tienen límite de longitud de línea conocido. Las búsquedas se ejecutaron correctamente en un archivo de 128 MB que no contenía un solo <LF>.

Los datos canalizados y la entrada redirigida están limitados a 8191 bytes por línea. Este límite es una "característica" de FINDSTR. No es inherente a las tuberías ni a la redirección. FINDSTR usando stdin redirigido o entrada canalizada nunca coincidirá con ninguna línea que sea> = 8k bytes. Las líneas> = 8k generan un mensaje de error para stderr, pero ERRORLEVEL sigue siendo 0 si la cadena de búsqueda se encuentra en al menos una línea de al menos un archivo.

Tipo de búsqueda predeterminado: Literal vs Expresión regular
/C:"string" : el valor predeterminado es / L literal. Combinar explícitamente la opción / L con / C: "string" ciertamente funciona pero es redundante.

"string argument"- El valor predeterminado depende del contenido de la primera cadena de búsqueda. (Recuerde que <space> se usa para delimitar las cadenas de búsqueda). Si la primera cadena de búsqueda es una expresión regular válida que contiene al menos un metacarácter sin escape, todas las cadenas de búsqueda se tratan como expresiones regulares. De lo contrario, todas las cadenas de búsqueda se tratan como literales. Por ejemplo, "51.4 200"se tratará como dos expresiones regulares porque la primera cadena contiene un punto sin escape, mientras "200 51.4"que se tratará como dos literales porque la primera cadena no contiene metacaracteres.

/G:file- El valor predeterminado depende del contenido de la primera línea no vacía en el archivo. Si la primera cadena de búsqueda es una expresión regular válida que contiene al menos un meta-carácter sin escape, entonces todas las cadenas de búsqueda se tratan como expresiones regulares. De lo contrario, todas las cadenas de búsqueda se tratan como literales.

Recomendación: siempre especifique explícitamente /Lla opción literal o /Rla opción de expresión regular cuando use "string argument"o /G:file.

ERROR: especificar varias cadenas de búsqueda literales puede dar resultados poco confiables

El siguiente ejemplo FINDSTR simple no puede encontrar una coincidencia, aunque debería.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Este error ha sido confirmado en Windows Server 2003, Windows XP, Vista y Windows 7.

Según los experimentos, FINDSTR puede fallar si se cumplen todas las condiciones siguientes:

  • La búsqueda está utilizando múltiples cadenas de búsqueda literales
  • Las cadenas de búsqueda son de diferentes longitudes.
  • Una cadena de búsqueda corta tiene cierta cantidad de superposición con una cadena de búsqueda más larga
  • La búsqueda distingue entre mayúsculas y minúsculas (sin /Iopción)

En cada falla que he visto, siempre es una de las cadenas de búsqueda más cortas que falla.

Para obtener más información, consulte ¿Por qué este ejemplo FINDSTR con múltiples cadenas de búsqueda literales no encuentra una coincidencia?

Citas y backslahses dentro de los argumentos de la línea de comandos
Nota: los comentarios del usuario MC ND reflejan las reglas realmente complicadas para esta sección. Hay 3 fases de análisis distintas involucradas:

  • Primero cmd.exe puede requerir que algunas comillas se escapen como ^ "(realmente nada que ver con FINDSTR)
  • Siguiente FINDSTR utiliza el analizador de argumentos MS C / C ++ anterior a 2008 , que tiene reglas especiales para "y \
  • Una vez que finaliza el analizador de argumentos, FINDSTR trata adicionalmente \ seguido de un carácter alfanumérico como literal, pero \ seguido de un carácter no alfanumérico como un carácter de escape

El resto de esta sección resaltada no es 100% correcta. Puede servir como guía para muchas situaciones, pero las reglas anteriores son necesarias para una comprensión total.

Cita de escape dentro de las cadenas de búsqueda de línea de comando Las
comillas dentro de las cadenas de búsqueda de línea de comando se deben escapar con una barra diagonal inversa como \". Esto es cierto tanto para las cadenas de búsqueda literales como de expresiones regulares. Esta información ha sido confirmada en XP, Vista y Windows 7.

Nota: La cotización también puede necesitar escapar para el analizador CMD.EXE, pero esto no tiene nada que ver con FINDSTR. Por ejemplo, para buscar una sola cita, puede usar:

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

Escape de barra diagonal dentro de las cadenas de búsqueda literales de la línea de comandos La
barra diagonal inversa en una cadena de búsqueda literal normalmente se puede representar como \o como \\. Son típicamente equivalentes. (Puede haber casos inusuales en Vista donde la barra invertida siempre se debe escapar, pero ya no tengo una máquina Vista para probar) .

Pero hay algunos casos especiales:

Al buscar barras invertidas consecutivas, se deben escapar todas menos la última . La última barra invertida se puede escapar opcionalmente.

  • \\puede codificarse como \\\o\\\\
  • \\\puede codificarse como \\\\\o\\\\\\

Buscar una o más barras diagonales inversas antes de una cita es extraño. La lógica sugeriría que la cita se debe escapar, y cada una de las barras diagonales inversas principales necesitarían escapar, ¡pero esto no funciona! En cambio, cada una de las barras diagonales inversas deben tener doble escape, y la cita se escapa normalmente:

  • \" debe codificarse como \\\\\"
  • \\" debe codificarse como \\\\\\\\\"

Como se señaló anteriormente, una o más comillas escapadas también pueden requerir escapar con ^el analizador CMD

La información en esta sección ha sido confirmada en XP y Windows 7.

Retroceso de escape dentro de las cadenas de búsqueda de expresiones regulares de la línea de comandos

  • Solo Vista: la barra invertida en una expresión regular debe tener doble escape como \\\\, o bien escapar solo dentro de un conjunto de clases de caracteres como [\\]

  • XP y Windows 7: la barra invertida en una expresión regular siempre se puede representar como [\\]. Normalmente se puede representar como \\. Pero esto nunca funciona si la barra inclinada invertida precede a una cita escapada.

    Una o más barras inclinadas invertidas antes de una cotización escapada deben ser doblemente escapadas o codificadas como [\\]

    • \"puede codificarse como \\\\\"o[\\]\"
    • \\"puede codificarse como \\\\\\\\\"o [\\][\\]\"o\\[\\]\"

Cita y barra
invertida de escape dentro de / G: cadenas de búsqueda literal de ARCHIVO Las comillas y las barras invertidas independientes dentro de un archivo de cadena de búsqueda literal especificado por / G: archivo no necesitan escapar, pero pueden serlo.

"y \"son equivalentes

\y \\son equivalentes

Si la intención es encontrar \\, entonces se debe escapar al menos la barra diagonal inversa inicial. Ambos \\\y \\\\trabajo.

Si la intención es encontrar \", entonces por lo menos debe ser escapado de la barra invertida inicial. Tanto \\"y \\\"trabajo.

Cita de escape y barra invertida dentro de / G: cadenas de búsqueda de expresiones regulares de ARCHIVO
Este es el caso en el que las secuencias de escape funcionan según lo esperado según la documentación. La cita no es un metacarácter regex, por lo que no necesita ser escapado (pero puede serlo). La barra invertida es un metacarácter regex, por lo que debe escaparse.

Límites de caracteres para los parámetros de la línea de comandos: transformación ASCII extendida
El carácter nulo (0x00) no puede aparecer en ninguna cadena en la línea de comandos. Cualquier otro carácter de un solo byte puede aparecer en la cadena (0x01 - 0xFF). Sin embargo, FINDSTR convierte muchos caracteres ASCII extendidos que encuentra dentro de los parámetros de la línea de comandos en otros caracteres. Esto tiene un gran impacto de dos maneras:

1) Muchos caracteres ASCII extendidos no coincidirán si se usan como una cadena de búsqueda en la línea de comando. Esta limitación es la misma para búsquedas literales y expresiones regulares. Si una cadena de búsqueda debe contener ASCII extendido, entonces se /G:FILEdebe usar la opción en su lugar.

2) FINDSTR puede no encontrar un archivo si el nombre contiene caracteres ASCII extendidos y el nombre del archivo se especifica en la línea de comando. Si un archivo para buscar contiene ASCII extendido en el nombre, entonces se /F:FILEdebe usar la opción en su lugar.

Aquí hay una lista completa de transformaciones de caracteres ASCII extendidas que FINDSTR realiza en cadenas de línea de comandos. Cada carácter se representa como el valor del código de byte decimal. El primer código representa el carácter tal como se proporciona en la línea de comando, y el segundo código representa el carácter en el que se transforma. Nota: esta lista se compiló en una máquina estadounidense. No sé qué impacto pueden tener otros idiomas en esta 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

Cualquier carácter> 0 que no esté en la lista anterior se trata como sí mismo, incluidos <CR>y < LF>. La forma más fácil de incluir caracteres impares como <CR>y <LF>es colocarlos en una variable de entorno y usar la expansión retrasada dentro del argumento de la línea de comandos.

Límites de caracteres para las cadenas que se encuentran en los archivos especificados por las opciones / G: FILE y / F: FILE
El carácter nul (0x00) puede aparecer en el archivo, pero funciona como el terminador de cadena C. Cualquier carácter después de un carácter nulo se trata como una cadena diferente como si estuviera en otra línea.

Los caracteres <CR>y <LF>se tratan como terminadores de línea que terminan una cadena, y no se incluyen en la cadena.

Todos los demás caracteres de un solo byte se incluyen perfectamente dentro de una cadena.

Búsqueda de archivos Unicode
FINDSTR no puede buscar correctamente la mayoría de Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) porque no puede buscar bytes nul y Unicode generalmente contiene muchos bytes nul.

Sin embargo, el comando TYPE convierte UTF-16LE con BOM en un conjunto de caracteres de un solo byte, por lo que un comando como el siguiente funcionará con UTF-16LE con BOM.

type unicode.txt|findstr "search"

Tenga en cuenta que los puntos de código Unicode que no son compatibles con su página de códigos activa se convertirán en ?caracteres.

Es posible buscar UTF-8 siempre que su cadena de búsqueda contenga solo ASCII. Sin embargo, la salida de la consola de cualquier carácter UTF-8 de varios bytes no será correcta. Pero si redirige la salida a un archivo, el resultado se codificará correctamente UTF-8. Tenga en cuenta que si el archivo UTF-8 contiene una lista de materiales, entonces la lista de materiales se considerará como parte de la primera línea, lo que podría descartar una búsqueda que coincida con el comienzo de una línea.

Es posible buscar caracteres UTF-8 de varios bytes si coloca su cadena de búsqueda en un archivo de búsqueda codificado UTF-8 (sin BOM) y utiliza la opción / G.

Fin de la línea
FINDSTR rompe las líneas inmediatamente después de cada <LF>. La presencia o ausencia de <CR> no tiene impacto en los saltos de línea.

Buscar en saltos de línea
Como se esperaba, el. metacarácter regex no coincidirá con <CR> o <LF>. Pero es posible buscar a través de un salto de línea usando una cadena de búsqueda de línea de comando. Tanto los caracteres <CR> como <LF> deben coincidir explícitamente. Si se encuentra una coincidencia de varias líneas, solo se imprime la primera línea de la coincidencia. FINDSTR luego vuelve a la segunda línea de la fuente y comienza la búsqueda nuevamente, una especie de función de "mirar hacia adelante".

Suponga que TEXT.TXT tiene estos contenidos (podría ser estilo Unix o Windows)

A
A
A
B
A
A

Entonces este guión

@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

da estos resultados

1:A
2:A
5:A

La búsqueda en saltos de línea con la opción / G: FILE es imprecisa porque la única forma de hacer coincidir <CR> o <LF> es a través de una expresión de rango de clase de caracteres regex que emparede los caracteres EOL.

  • [<TAB>-<0x0B>] coincide con <LF>, pero también coincide con <TAB> y <0x0B>

  • [<0x0C>-!] coincide con <CR>, pero también coincide con <0x0C> y!

    Nota: lo anterior son representaciones simbólicas del flujo de bytes regex ya que no puedo representar gráficamente los caracteres.

La respuesta continuó en la parte 2 a continuación ...

dbenham
fuente
46
Completitud sobresaliente. Si solo todas las respuestas en internet fueran así.
Mike Viens
1
nos hemos encontrado con un problema addpath.batde Q141344 y findstr, que puede estar relacionado con el problema que cuelga Win7 mencionado anteriormente. He creado una sala de chat para tratar de rastrear esto, para cualquiera que esté interesado: chat.stackoverflow.com/rooms/13177/…
matt wilkie
2
EDITAR: visualización descrita de los caracteres de control como puntos en XP. También se documentaron errores /Sy /Dopciones derivadas de nombres cortos de archivos 8.3.
dbenham
1
EDITAR - 1) Los nombres de archivo dentro del archivo especificado por / F: FILE no se deben citar. 2) La transformación de caracteres ASCII extendidos afecta tanto a las cadenas de búsqueda como a los nombres de archivos cuando se suministran en la línea de comando.
dbenham
1
EDITAR: error agregado en el que se ignora la última línea de entrada canalizada si consta de un solo carácter sin<LF>
dbenham
64

La respuesta continúa de la parte 1 anterior : me he encontrado con el límite de respuesta de 30,000 caracteres :-(

Compatibilidad con expresiones regulares limitadas (expresiones regulares) La compatibilidad con
FINDSTR para expresiones regulares es extremadamente limitada. Si no está en la documentación de AYUDA, no es compatible.

Más allá de eso, las expresiones de expresiones regulares que se admiten se implementan de una manera completamente no estándar, de modo que los resultados pueden ser diferentes de lo que cabría esperar de algo como grep o perl.

La posición de línea de expresión fija ancla ^ y $
^ coincide con el comienzo del flujo de entrada, así como con cualquier posición que siga inmediatamente a un <LF>. Como FINDSTR también rompe líneas después de <LF>, una expresión regular simple de "^" siempre coincidirá con todas las líneas dentro de un archivo, incluso un archivo binario.

$coincide con cualquier posición inmediatamente anterior a un <CR>. Esto significa que una cadena de búsqueda regex que contenga $nunca coincidirá con ninguna línea dentro de un archivo de texto de estilo Unix, ni coincidirá con la última línea de un archivo de texto de Windows si le falta el marcador EOL de <CR> <LF>.

Nota: Como se discutió anteriormente, la entrada canalizada y redirigida a FINDSTR puede haber <CR><LF>agregado que no está en la fuente. Obviamente, esto puede afectar una búsqueda de expresiones regulares que utiliza $.

Cualquier cadena de búsqueda con caracteres antes ^o después $siempre fallará en encontrar una coincidencia.

Opciones posicionales / B / E / X
Las opciones posicionales funcionan igual que ^y $, excepto que también funcionan para cadenas de búsqueda literales.

/ B funciona igual que ^al comienzo de una cadena de búsqueda de expresiones regulares.

/ E funciona igual que $al final de una cadena de búsqueda de expresiones regulares.

/ X funciona igual que tener ambos ^al principio y$ al final de una cadena de búsqueda de expresiones regulares.

El límite de palabras de expresiones regulares
\< debe ser el primer término en la expresión regular. La expresión regular no coincidirá con nada si otros caracteres le preceden.\<corresponde al principio de la entrada, el comienzo de una línea (la posición que sigue inmediatamente a un <LF>) o la posición que sigue inmediatamente a cualquier carácter "sin palabra". El siguiente carácter no necesita ser un carácter de "palabra".

\>debe ser el último término en la expresión regular. La expresión regular no coincidirá con nada si algún otro personaje la sigue. \>corresponde al final de la entrada, la posición inmediatamente anterior a un <CR>, o la posición inmediatamente anterior a cualquier carácter "sin palabra". El carácter anterior no necesita ser un carácter de "palabra".

Aquí hay una lista completa de caracteres "que no son palabras", representados como el código de byte decimal. Nota: esta lista se compiló en una máquina estadounidense. No sé qué impacto pueden tener otros idiomas en esta 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

Rangos de clases de caracteres de expresión regular [xy]
Los rangos de clases de caracteres no funcionan como se esperaba. Vea esta pregunta: ¿Por qué los hallazgos no manejan el caso correctamente (en algunas circunstancias)? , junto con esta respuesta: https://stackoverflow.com/a/8767815/1012053 .

El problema es que FINDSTR no clasifica los caracteres por su valor de código de byte (comúnmente conocido como el código ASCII, pero ASCII solo se define de 0x00 a 0x7F). La mayoría de las implementaciones de expresiones regulares tratarían [AZ] como todas las mayúsculas en inglés en mayúsculas. Pero FINDSTR usa una secuencia de clasificación que corresponde aproximadamente a cómo funciona SORT. Por lo tanto, [AZ] incluye el alfabeto inglés completo, tanto mayúsculas como minúsculas (excepto "a"), así como caracteres alfabéticos que no están en inglés con signos diacríticos.

A continuación se muestra una lista completa de todos los caracteres admitidos por FINDSTR, ordenados en la secuencia de clasificación utilizada por FINDSTR para establecer rangos de clase de caracteres regex. Los caracteres se representan como su valor de código de byte decimal. Creo que la secuencia de clasificación tiene más sentido si los caracteres se ven usando la página de códigos 437. Nota: esta lista se compiló en una máquina estadounidense. No sé qué impacto pueden tener otros idiomas en esta 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

Límite de término de clase de carácter de expresión regular y ERROR
FINDSTR no solo está limitado a un máximo de 15 términos de clase de carácter dentro de una expresión regular, sino que no puede manejar adecuadamente un intento de exceder el límite. El uso de 16 o más términos de clase de caracteres da como resultado una ventana emergente interactiva de Windows que dice "La utilidad Buscar cadena (QGREP) ha encontrado un problema y debe cerrarse. Disculpe las molestias". El texto del mensaje varía ligeramente según la versión de Windows. Aquí hay un ejemplo de un FINDSTR que fallará:

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]

Este error fue reportado por el usuario de DosTips Judago aquí . Se ha confirmado en XP, Vista y Windows 7.

Las búsquedas de expresiones regulares fallan (y pueden colgar indefinidamente) si incluyen el código de byte 0xFF (decimal 255)
Cualquier búsqueda de expresiones regulares que incluya el código de byte 0xFF (255 decimal) fallará. Falla si el código de byte 0xFF se incluye directamente, o si se incluye implícitamente dentro de un rango de clase de caracteres. Recuerde que los rangos de clase de caracteres FINDSTR no clasifican caracteres en función del valor del código de byte. El carácter <0xFF>aparece relativamente temprano en la secuencia de colación entre los caracteres <space>y <tab>. Por lo tanto, cualquier rango de clase de personaje que incluya ambos <space>y <tab>fallará.

El comportamiento exacto cambia ligeramente según la versión de Windows. Windows 7 se bloquea indefinidamente si se incluye 0xFF. XP no se bloquea, pero siempre no puede encontrar una coincidencia y ocasionalmente imprime el siguiente mensaje de error: "El proceso intentó escribir en una tubería inexistente".

Ya no tengo acceso a una máquina Vista, por lo que no he podido probar en Vista.

Error de expresión regular: .y [^anySet]puede coincidir con el final del archivo
El metacarácter de expresión regular .solo debe coincidir con cualquier carácter que no sea <CR>o <LF>. Hay un error que le permite coincidir con el Fin de archivo si la última línea del archivo no termina con <CR>o <LF>. Sin embargo, .no coincidirá con un archivo vacío.

Por ejemplo, un archivo llamado "test.txt" que contiene una sola línea de x, sin terminar <CR>o <LF>, coincidirá con lo siguiente:

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

Este error ha sido confirmado en XP y Win7.

Lo mismo parece ser cierto para los conjuntos de caracteres negativos. Algo así [^abc]coincidirá con Fin de archivo. Los juegos de caracteres positivos [abc]parecen funcionar bien. Solo he probado esto en Win7.

dbenham
fuente
1
FindStr también tiene errores al tratar con archivos grandes. Los archivos> 2 GB pueden hacer que findtr se bloquee. No siempre sucede. Al confirmar el error, busqué un archivo que tenía 2.3 GB que no se colgó. Se cuelga incluso si busca solo un archivo. La solución es canalizar la salida de typeen findstr.
Desilusionado el
Probablemente también valga la pena mencionar explícitamente que findstradmite múltiples /c:cadenas de búsqueda. Sé que tus respuestas demuestran esto. Pero es algo que no está documentado; y me sorprendió bastante conocer la función después de haberla usado findstrsin ella durante algunos años.
Desilusionado el
@CraigYoung: tienes razón acerca de las fuentes de cadena de búsqueda. Edité mi respuesta, gracias.
dbenham
1
En una investigación adicional, parece una variación en el LFproblema que documentó. Me di cuenta de que mi archivo de prueba no terminaba LFporque lo usé copyen modo de adición para crearlo. Puse una sesión de línea de comando para demostrar el problema en una respuesta ( stackoverflow.com/a/22943056/224704 ). Tenga en cuenta que la entrada no se redirige y, sin embargo, la búsqueda se bloquea. El mismo comando de búsqueda no se cuelga con archivos más pequeños que tampoco terminan de manera similar LF.
Desilusionado el
1
Nuevo hallazgo (Windows 7): 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 clases de personajes) - ErrorLevel = -1073740791 (0xC0000409), la ventana de diálogo de error : Find String (QGREP) Utility has stopped working; después de eliminar una clase o dos *\.
metacaracteres
7

findstr a veces se cuelga inesperadamente al buscar archivos grandes.

No he confirmado las condiciones exactas o los tamaños de los límites. Sospecho que cualquier archivo de más de 2 GB puede estar en riesgo.

He tenido experiencias mixtas con esto, por lo que es más que solo el tamaño del archivo. Parece que puede ser una variación de FINDSTR que se bloquea en XP y Windows 7 si la entrada redirigida no termina con LF , pero como se demostró, este problema particular se manifiesta cuando la entrada no se redirige.

La siguiente sesión de línea de comandos (Windows 7) muestra cómo se findstrpuede bloquear al buscar un archivo de 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>

Tenga en cuenta que he verificado en un editor hexadecimal que todas las líneas están terminadas con CRLF. La única anomalía es que el archivo finaliza 0x1Adebido a la forma en que copyfunciona . Sin embargo, tenga en cuenta que esta anomalía no causa un problema en los archivos "pequeños" .

Con pruebas adicionales, he confirmado lo siguiente:

  • El uso copycon la /bopción de archivos binarios evita la adición del 0x1Acarácter y findstrno se bloquea en el archivo de 3 GB.
  • Terminar el archivo de 3GB con un carácter diferente también hace findstrque se cuelgue.
  • los 0x1A personaje no causa ningún problema en un archivo "pequeño". (Del mismo modo para otros caracteres finales).
  • Agregar CRLFdespués 0x1Aresuelve el problema. ( LFpor sí solo probablemente sería suficiente).
  • Utilizando typepara canalizar el archivo en findstrobras sin colgar. (Esto podría deberse a un efecto secundario de cualquiera typeo |que inserta un Fin de línea adicional).
  • Usar la entrada redirigida <también hace findstrque se cuelgue. Pero esto se espera; como se explica en la publicación de dbenham : "la entrada redirigida debe terminar en LF" .
Desilusionado
fuente
1
+1, puedo confirmar el problema en mi máquina Win7. Un archivo con un tamaño exacto de 2GiB se colgó cuando el último carácter no estaba <LF>. Un archivo dos bytes más pequeño no se colgó. ¡Muy asqueroso!
dbenham
6

Cuando varios comandos están encerrados entre paréntesis y hay archivos redirigidos a todo el bloque:

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

... entonces los archivos permanecen abiertos mientras los comandos en el bloque estén activos, por lo que los comandos pueden mover el puntero de los archivos redirigidos. Los comandos MORE y FIND mueven el puntero del archivo Stdin al comienzo del archivo antes de procesarlo, por lo que el mismo archivo puede procesarse varias veces dentro del bloque. Por ejemplo, este código:

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

... produce el mismo resultado que este:

< 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 el mismo resultado que este:

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

FINDSTR es diferente; sí no mover el puntero del archivo Stdin desde su posición actual. Por ejemplo, este código inserta una nueva línea después de una línea de búsqueda:

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

Podemos hacer un buen uso de esta función con la ayuda de un programa auxiliar que nos permita mover el puntero de un archivo redirigido, como se muestra en este ejemplo .

Este comportamiento fue reportado por primera vez por jeb en esta publicación .


EDITAR 2018-08-18 : Nuevo error FINDSTR reportado

El comando FINDSTR tiene un error extraño que ocurre cuando este comando se usa para mostrar caracteres en color Y la salida de dicho comando se redirige al dispositivo CON. Para obtener detalles sobre cómo usar el comando FINDSTR para mostrar texto en color, consulte este tema .

Cuando la salida de esta forma de comando FINDSTR se redirige a CON, sucede algo extraño después de que el texto se emite en el color deseado: todo el texto después de que se emite como caracteres "invisibles", aunque una descripción más precisa es que el texto es salida como texto negro sobre fondo negro. El texto original aparecerá si usa el comando COLOR para restablecer los colores de primer plano y fondo de toda la pantalla. Sin embargo, cuando el texto es "invisible" podríamos ejecutar un comando SET / P, por lo que todos los caracteres ingresados ​​no aparecerán en la pantalla. Este comportamiento puede usarse para ingresar contraseñas.

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"
Aacini
fuente
2

Me gustaría informar un error relacionado con la sección Fuente de datos para buscar en la primera respuesta cuando se usa en dash (-) o em dash (-) dentro del nombre de archivo.

Más específicamente, si está a punto de utilizar la primera opción: nombres de archivo especificados como argumentos , no se encontrará el archivo. Tan pronto como utilice la opción 2 - stdin a través de la redirección o 3 - flujo de datos desde una tubería , findtr encontrará el archivo.

Por ejemplo, este script por lotes simple:

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

imprimirá:

Nombre de archivo con en dash:

  1. Como argumento
    FINDSTR: No se puede abrir el nombre de archivo con - dash.txt

  2. Como stdin a través de la redirección
    , soy el archivo con un guión.

  3. Como flujo de datos de una tubería
    , soy el archivo con un guión.

Nombre de archivo con em dash:

  1. Como argumento
    FINDSTR: No se puede abrir el nombre de archivo con - dash.txt

  2. Como stdin a través de la redirección
    , soy el archivo con un guión em.

  3. Como flujo de datos de una tubería
    , soy el archivo con un guión em.

Espero eso ayude.

METRO.

matro
fuente
1
Hola matro, aunque tus comentarios pueden ser correctos, no estoy seguro de que no aborden la pregunta real.
Wai Ha Lee
Creo que este es un problema Unicode, que FINDSTR no admite. La redirección CMD.EXE puede abrir correctamente un nombre de archivo con unicode, al igual que el comando TYPE. Pero en algún momento, FINDSTR convierte tanto el en-dash como el em-dash en un guión normal, y, por supuesto, el sistema operativo no puede encontrar ese nombre. Si crea otro archivo sustituyendo un guión por el en-dash y / o em-dash, FINDSTR buscará el archivo de guión si se le proporciona un nombre que contenga en-dash o em-dash.
dbenham
Clasificaría este problema como una limitación en lugar de un error.
dbenham
En realidad, esto no es tanto un problema unicode, ya que se extiende ASCII. Ya documenté este problema en mi respuesta original bajo el título Límites de caracteres para los parámetros de la línea de comandos: transformación ASCII extendida . FINDSTR transforma una serie de códigos ASCII extendidos en ASCII verdadero "relacionado", incluidos en-dash y em-dash.
dbenham
1

El findstrcomando establece el ErrorLevel(o código de salida) en uno de los siguientes valores, dado que no hay modificadores inválidos o incompatibles y ninguna cadena de búsqueda excede el límite de longitud aplicable:

  • 0 cuando se encuentra al menos una sola coincidencia en una línea en todos los archivos especificados;
  • 1 de otra manera;

Se considera que una línea contiene una coincidencia cuando:

  • no /Vse da ninguna opción y la expresión de búsqueda ocurre al menos una vez;
  • /Vse da la opción y la expresión de búsqueda no aparece;

Esto significa que la /Vopción también cambia el valor devuelto ErrorLevel, ¡pero no solo lo revierte!

Por ejemplo, cuando tiene un archivo test.txtcon dos líneas, una de las cuales contiene la cadena textpero la otra no, ambas findstr "text" "test.txt"y findstr /V "text" "test.txt"devuelven una ErrorLevelde 0.

Básicamente puede decir: si findstrdevuelve al menos una línea, ErrorLevelse establece en 0, de lo contrario a 1.

Tenga en cuenta que la /Mopción no afecta el ErrorLevelvalor, solo altera la salida.

(Solo por completo: el findcomando se comporta exactamente de la misma manera con respecto a la /Vopción y ErrorLevel; la /Copción no afecta ErrorLevel).

aschipfl
fuente
1

FINDSTR tiene un error de color que describí y resolví en /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Para resumir ese hilo, el error es que si la entrada se canaliza a FINDSTR dentro de un bloque de código entre paréntesis, los códigos de color de escape ANSI en línea dejan de funcionar en los comandos ejecutados más tarde. Un ejemplo de códigos de colores en línea es:echo %magenta%Alert: Something bad happened%yellow% (donde magenta y amarillo son variables definidas anteriormente en el archivo .bat como los códigos de color de escape ANSI correspondientes).

Mi solución inicial fue llamar a una subrutina de no hacer nada después de FINDSTR. De alguna manera, la llamada o el retorno "restablece" lo que sea necesario restablecer.

Más tarde descubrí otra solución que presumiblemente es más eficiente: coloque la frase FINDSTR entre paréntesis, como en el siguiente ejemplo: echo success | ( FINDSTR /R success ) Colocar la frase FINDSTR dentro de un bloque anidado de código parece aislar el error de código de color de FINDSTR para que no afecte lo que está fuera del anidado bloquear. Quizás esta técnica también resolverá algunos otros efectos secundarios FINDSTR no deseados .

Dolores Stevens
fuente
Gran hallazgo. Pero sus reglas se pueden simplificar (al menos en mi máquina Windows 10 empresarial). FINDSTR evita que todas las secuencias de escape de la consola funcionen para los comandos posteriores dentro del mismo bloque de comandos. No importa si FINDSTR lee una tubería, una entrada redirigida o un archivo. La falla de la secuencia de escape no está restringida a códigos de colores. Un bloque de comandos es cualquier conjunto de comandos entre paréntesis y / o comandos concatenados mediante &, &&, o ||
dbenham
@dbenham: Buena generalización del problema. ¿Sabes si mi solución, anidar la frase FINDSTR entre paréntesis, también funciona en el caso general? ¿Y sabes si mi solución tiene efectos secundarios indeseables?
Dolores Stevens
No hice ninguna prueba exhaustiva, pero sí, los paréntesis anidados parecen ser una solución general, y no puedo pensar en posibles efectos secundarios indeseables.
dbenham
-1

/ D consejo para múltiples directorios: ponga su lista de directorios antes de la cadena de búsqueda. Todo esto funciona:

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

Como se esperaba, la ruta es relativa a la ubicación si no inicia los directorios con \. Rodear la ruta con "es opcional si no hay espacios en los nombres de directorio. El final \es opcional. La salida de ubicación incluirá cualquier ruta que le des. Funcionará con o sin rodear la lista de directorios con ".

Gordon
fuente
No veo nada indocumentado aquí. La opción / D se describe en la ayuda integrada. Esta no es una pregunta para obtener consejos generales sobre cómo usar FINDSTR. Está estrictamente destinado a enumerar características no documentadas, limitaciones y / o errores.
dbenham
1
@dbenham es cierto, no es realmente indocumentado, pero descubrí que tenía que buscar con los resultados de FindStr para obtener los resultados que quería y estoy compartiendo lo que descubrí que funcionaba para que la gente no perdiera el tiempo experimentando con comandos que NO funcionan. HTH (estoy triste que no les gusta mi entrada - que sólo se pretende que sea constructiva)
Gordon
En mi humilde opinión, el modificador / D se describe claramente en la ayuda integrada: /D:dirlist Search a semicolon-delimited list of directoriesy se coloca antes de la cadena de búsqueda, por lo que no entiendo qué es exactamente lo que "encontró" sobre el modificador / D (y cuáles son los "comandos que NO funciona ") ...
Aacini
@Aacini en muchos idiomas, el orden de los atributos no importa. Entiendo la documentación de las findstrlistas / D primero. Sí, no tengo ningún argumento con la característica que se está documentando, simplemente no está documentado sobre el problema que importa el orden de los atributos. Hago muy poco trabajo en la línea de comandos, por lo que cuando estaba manipulando un comando, sin darme cuenta de que el orden marcaba la diferencia, solo estaba agregando los atributos a medida que los recibía (y alfabéticamente, C precede a D). Me estaba frustrando mucho y he compartido mi experiencia "encontrada" con cualquier otra persona que no trabaja mucho con la línea de comandos.
Gordon
1
El orden de los atributos opcionales generalmente no importa. La findstrdocumentación especifica que la stringsparte NO es opcional y que debe colocarla después de los atributos opcionales y antes de la lista de nombre de archivo opcional . Si "lo que encontró" es que usar un comando sin seguir su formato de uso causa un error, entonces ese punto está bien documentado. Consulte Sintaxis del comando : "La sintaxis aparece en el orden en que debe escribir un comando y los parámetros que lo siguen"
Aacini