Saltar al contenido

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

Solución:

Prefacio
Gran parte de la información en esta respuesta se ha recopilado en función de experimentos ejecutados 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:

nombre de archivo: 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 de archivo siempre incluirá cualquier información de ruta proporcionada. Se agregará información de ruta adicional si el /S se 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 del nombre de archivo se puede evitar cuando se buscan varios archivos mediante el uso de comodines no estándar (y poco documentados) < y >. Las reglas exactas sobre cómo funcionan estos comodines se pueden encontrar aquí. Por último, puede ver este ejemplo de cómo funcionan los comodines no estándar con FINDSTR.

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

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

texto = La representación binaria de la línea coincidente, incluyendo cualquier y / o . No queda nada fuera de la salida binaria, de modo que este ejemplo que coincide con todas las líneas producirá una copia binaria exacta del archivo original.

FINDSTR "^" FILE >FILE_COPY

La opción / A establece el color de fileName :, lineNumber: y lineOffset: salida solamente. El texto de la línea coincidente siempre se imprime 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 ningún efecto si la salida se redirige a un archivo o se canaliza. Consulte la edición 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 las líneas coincidentes como puntos (puntos) en la pantalla. Los siguientes caracteres de control son excepciones; se muestran como ellos mismos: 0x09 Tab, 0x0A LineFeed, 0x0B Vertical Tab, 0x0C Form Feed, 0x0D Carriage Return.

XP FINDSTR también convierte varios caracteres ASCII extendidos en puntos. Los caracteres ASCII extendidos que se muestran como puntos en XP son los mismos que se transforman cuando se suministran en la línea de comandos. Ver el “Límites de caracteres para los parámetros de la línea de comandos: transformación ASCII ampliada” sección, 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ó una coincidencia en al menos una línea de al menos un archivo.
  • 1 (falla)
    • No se encontró ninguna coincidencia en ninguna línea de ningún archivo.
    • Color no válido especificado por /A:xx opción
  • 2 (error)
    • Opciones incompatibles /L y /R ambos especificados
    • Falta argumento después /A:, /F:, /C:, /D:, o /G:
    • Archivo especificado por /F:file o /G:file extraviado
  • 255 (error)
    • Demasiados términos de clase de caracteres de expresión regular
      ver Límite de término de clase de carácter regex y ERROR en la parte 2 de la respuesta

Fuente de datos para buscar (Actualizado basado en pruebas con Windows 7)

Findstr puede buscar datos de solo una de las siguientes fuentes:

  • nombres de archivo especificados como argumentos y / o utilizando el /F:file opción.

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

  • flujo de datos de 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:file pueden combinarse. Se pueden utilizar varios argumentos de nombre de archivo. Si es múltiple /F:file se especifican opciones, luego solo se usa la última. Se permiten comodines en los argumentos del nombre de archivo, pero no dentro del archivo al que apunta /F:file.

Fuente de cadenas de búsqueda (Actualizado basado en pruebas con Windows 7)

los /G:file y /C:string las opciones pueden combinarse. Múltiple /C:string se pueden especificar opciones. Si es múltiple /G:file se especifican opciones, luego solo se usa la última. Si alguno /G:file o /C:string se utiliza, entonces se supone que todos los argumentos que no son de opción son archivos para buscar. Si ninguno /G:file ni /C:string se utiliza, entonces el primer argumento que no es una opción se trata como una lista de términos de búsqueda delimitada por espacios.

Los nombres de archivo no deben estar entrecomillados dentro del archivo cuando se utiliza el /F:FILE opción.

Los nombres de archivo pueden contener espacios y otros caracteres especiales. La mayoría de los comandos requieren que dichos nombres de archivo estén entrecomillados. Pero el FINDSTR /F:files.txt La opción requiere que los nombres de archivo dentro de files.txt NO estén entre comillas. El archivo no se encontrará si se cita el nombre.

ERROR: los nombres de archivo 8.3 cortos pueden /D y /S opciones

Al igual que con todos los comandos de Windows, FINDSTR intentará hacer coincidir tanto el nombre largo como el nombre corto 8.3 cuando busque 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.txt2 coincide porque el nombre corto correspondiente B9F64~1.TXT partidos. Esto es coherente con el comportamiento de todos los demás comandos de Windows.

Pero un error con el /D y /S opciones hace que los siguientes comandos solo encuentren b1.txt

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

El error previene b.txt2 de ser encontrado, así como todos los nombres de archivo que se ordenan después b.txt2 dentro del mismo directorio. Archivos adicionales que se ordenan antes, como a.txt, se encuentran. Archivos adicionales que se ordenan más tarde, como d.txt, se pasan por alto una vez que se ha activado el error.

Cada directorio buscado se trata de forma independiente. Por ejemplo, el /S La opción comenzaría a buscar con éxito en una carpeta secundaria después de no poder encontrar archivos en la carpeta principal, pero una vez que el error hace que se pierda un nombre de archivo corto en la carpeta secundaria, 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 desactivada. Por supuesto b.txt2 no se encontraría, pero c.txt se encontraría correctamente.

No todos los nombres cortos provocan 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 8.3 corto que comienza igual que un nombre normal que no requiere un nombre 8.3.

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

Caracteres no imprimibles y /P opción

los /P La opció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, el /P La opción solo omitirá 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 provoca la /P opción para omitir el archivo.

La entrada canalizada y redirigida puede tener <CR><LF> adjunto

Si la entrada se canaliza y el último carácter de la secuencia no es <LF>, luego FINDSTR 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 en realidad 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 es <LF>, luego FINDSTR agregará automáticamente <CR><LF> a la entrada. Sin embargo, XP y Windows 7 no modifican 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 con <LF>, FINDSTR se bloqueará indefinidamente una vez que llegue al final del archivo redirigido.

La última línea de datos canalizados se puede ignorar si consta de un solo carácter

Si la entrada se canaliza y la última línea consta de un solo carácter que no va seguido de <LF>, luego FINDSTR ignora por completo la última línea.

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

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

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

> echo x| findstr "^"
x

Informado por el usuario de DosTips Sponge Belly en un nuevo error de hallazgo. 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 letras de opción no distinguen entre mayúsculas y minúsculas, por lo que /i y /I son equivalentes.

Las opciones pueden tener el prefijo / 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 varios caracteres, como OFF o F :, y la opción de varios caracteres debe ser la última opción de la lista.

Las siguientes son formas equivalentes de expresar una búsqueda de expresiones regulares que no distinguen 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"

También se pueden cotizar opciones. Entonces /i, -i, "/i" y "-i" son todos equivalentes. Igualmente, /c:string, "/c":string, "/c:"string y "/c:string" son todos equivalentes.

Si una cadena de búsqueda comienza con un / o - literal, entonces el /C o /G se debe utilizar la opción. Gracias a Stephan por informar de esto en un comentario (desde que se eliminó).

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 excede 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 una FINDSTR: Out of memory error con ERRORLEVEL 2. Una longitud de expresión regular> 511 da como resultado FINDSTR: Search string too long. error.

En Windows XP, la longitud de la cadena de búsqueda es aparentemente más corta. Error de 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 127 bytes para búsquedas literales y regex.

Límites de longitud de línea

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

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 canalizaciones 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: expresión literal frente a expresión regular
/C:"string" – El valor predeterminado es / L literal. La combinación explícita de la opción / L con / C: “cadena” ciertamente funciona, pero es redundante.

"string argument" – El valor predeterminado depende del contenido de la primera cadena de búsqueda. (Recuérdalo se utiliza para delimitar 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 que "200 51.4" 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 del archivo. 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.

Recomendación: especificar siempre explícitamente /L opción literal o /R opción de expresión regular al usar "string argument" o /G:file.

ERROR: especificar varias cadenas de búsqueda literal puede dar resultados poco fiables

El siguiente ejemplo sencillo de FINDSTR no encuentra una coincidencia, aunque debería.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Este error se ha 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 utiliza múltiples cadenas de búsqueda literal.
  • Las cadenas de búsqueda son de diferentes longitudes.
  • Una cadena de búsqueda corta tiene cierta superposición con una cadena de búsqueda más larga
  • La búsqueda distingue entre mayúsculas y minúsculas (no /I opción)

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

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

Citas y revés dentro de los argumentos de la línea de comandos
Nota – Los comentarios del usuario MC ND reflejan las reglas horriblemente complicadas de esta sección. Hay 3 fases de análisis distintas involucradas:

  • El primer cmd.exe puede requerir que algunas comillas se escapen como ^ “(realmente no tiene nada que ver con FINDSTR)
  • Siguiente FINDSTR utiliza el analizador de argumentos de MS C / C ++ anterior a 2008, que tiene reglas especiales para “y
  • Una vez que finaliza el analizador de argumentos, FINDSTR además trata seguido de un carácter alfanumérico como literal, pero seguido de un carácter no alfanumérico como 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.

Escapar de cotización dentro de cadenas de búsqueda de línea de comando
Las citas dentro de las cadenas de búsqueda de la línea de comando deben escaparse con una barra invertida como
". Esto es cierto tanto para las cadenas de búsqueda literal como para las expresiones regulares. Esta información se ha confirmado en XP, Vista y Windows 7.

Nota: Es posible que la cita también deba escaparse 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

Escapar de barra invertida dentro de cadenas de búsqueda literal de línea de comando
La barra invertida en una cadena de búsqueda literal normalmente se puede representar como
o como \. Suelen ser equivalentes. (Puede haber casos inusuales en Vista donde la barra invertida siempre debe escaparse, pero ya no tengo una máquina Vista para probar).

Pero hay algunos casos especiales:

Al buscar barras diagonales inversas consecutivas, todas menos la última debe ser escapado. Opcionalmente, se puede escapar de la última barra inclinada invertida.

  • \ se puede codificar como \ o \\
  • \ se puede codificar como \\ o \\\

Buscar una o más barras invertidas antes de una cita es extraño. La lógica sugeriría que la cita debe escaparse, y cada una de las barras diagonales inversas iniciales tendría que escaparse, ¡pero esto no funciona! En su lugar, cada una de las barras diagonales inversas iniciales debe tener un doble escape, y la cita se escapa normalmente:

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

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

La información de esta sección se ha confirmado en XP y Windows 7.

Escapar de la barra invertida dentro de las cadenas de búsqueda de expresiones regulares de la línea de comando

  • Vista solamente: La barra invertida en una expresión regular debe tener doble escape como \\, o bien solo se escapó 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 invertida precede a una cita de escape.

    Una o más barras diagonales inversas antes de una cita de escape deben tener doble escape o codificarse como [\]

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

Escapar de cotización y barra invertida dentro de / G: cadenas de búsqueda literal de ARCHIVO

Las comillas independientes y las barras invertidas dentro de un archivo de cadena de búsqueda literal especificado por / G: file no necesitan escaparse, pero pueden serlo.

" y " son equivalentes.

y \ son equivalentes.

Si la intención es encontrar \, entonces al menos la barra invertida inicial debe escaparse. Ambos \ y \\ trabaja.

Si la intención es encontrar “, al menos se debe escapar la barra invertida inicial. Ambos \" y \" trabaja.

Escapar de cotización y barra invertida dentro de / G: cadenas de búsqueda de expresiones regulares FILE

Este es el único caso en el que las secuencias de escape funcionan como se esperaba según la documentación. Quote no es un metacarácter de expresión regular, por lo que no es necesario escapar (pero puede serlo). La barra invertida es un metacarácter de expresión regular, 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 comando. 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 comando en otros caracteres. Esto tiene un gran impacto de dos formas:

  1. Muchos caracteres ASCII extendidos no coincidirán entre sí si se utilizan como una cadena de búsqueda en la línea de comandos. Esta limitación es la misma para búsquedas literales y regex. Si una cadena de búsqueda debe contener ASCII extendido, entonces el /G:FILE en su lugar, debería utilizarse la opción.

  2. FINDSTR puede fallar al 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 que se va a buscar contiene ASCII extendido en el nombre, entonces el /F:FILE en su lugar, debería utilizarse la opción.

Aquí hay una lista completa de transformaciones de caracteres ASCII extendidas que FINDSTR realiza en cadenas de línea de comando. Cada carácter se representa como el valor del código de bytes decimal. El primer código representa el carácter que 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 de EE. UU. 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, incluido <CR> yLF>. La forma más sencilla de incluir caracteres extraños como <CR> y <LF> es ponerlos en una variable de entorno y usar la expansión retardada dentro del argumento de la línea de comandos.

Límites de caracteres para cadenas encontradas en 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. Los caracteres que siguen a un carácter nulo se tratan como una cadena diferente como si estuvieran en otra línea.

los <CR> y <LF> los caracteres 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 nulos y Unicode normalmente contiene muchos bytes nulos.

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 a ? 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 en 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 provocar 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 en UTF-8 (sin BOM) y usa la opción / G.

Fin de la línea

FINDSTR rompe líneas inmediatamente después de cada . La presencia o ausencia de no tiene ningún impacto en los saltos de línea.

Buscando a través de saltos de línea

Como era de esperar, el . El metacarácter de expresión regular no coincidirá o . Pero es posible buscar en un salto de línea usando una cadena de búsqueda de línea de comando. Ambos y los caracteres 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 en la fuente y comienza la búsqueda de nuevo, una especie de función de tipo “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

Buscar entre saltos de línea usando la opción / G: FILE es impreciso porque la única forma de hacer coincidir o es a través de una expresión de rango de clase de caracteres regex que empareja los caracteres EOL.

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

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

Nota: las anteriores son representaciones simbólicas del flujo de bytes de expresiones regulares, ya que no puedo representar gráficamente los caracteres.

La respuesta continúa en la parte 2 a continuación …

La respuesta continúa de parte 1 anterior: me he topado con el límite de respuesta de 30.000 caracteres 🙁

Compatibilidad con expresiones regulares limitadas (regex)

El soporte de FINDSTR para expresiones regulares es extremadamente limitado. Si no está en la documentación de AYUDA, no es compatible.

Más allá de eso, las expresiones regex que son compatibles se implementan de una manera completamente no estándar, de modo que los resultados pueden ser diferentes de los que se esperarían provenientes de algo como grep o perl.

Anclajes de posición de línea de expresiones regulares ^ y $
^ coincide con el comienzo del flujo de entrada, así como con cualquier posición inmediatamente siguiente a un . Dado que FINDSTR también rompe líneas después , una simple expresión regular 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 . Esto significa que una cadena de búsqueda de expresiones regulares que contiene $ 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 falta el marcador EOL de .

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

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

Opciones de posición / 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.

Límite de la palabra regex
< debe ser el primer término de la expresión regular. La expresión regular no coincidirá con nada si otros caracteres la preceden. < corresponde al comienzo mismo de la entrada, al comienzo de una línea (la posición que sigue inmediatamente a una ) o la posición que sigue inmediatamente a cualquier carácter “que no sea una palabra”. El siguiente carácter no necesita ser un carácter de “palabra”.

> debe ser el último término de la expresión regular. La expresión regular no coincidirá con nada si otros caracteres la siguen. > corresponde al final de la entrada, la posición inmediatamente anterior a un , o la posición inmediatamente anterior a cualquier carácter “que no sea una palabra”. No es necesario que el carácter anterior sea un carácter de “palabra”.

Aquí hay una lista completa de caracteres “que no son palabras”, representados como el código de bytes decimal. Nota: esta lista se compiló en una máquina de EE. UU. 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 Regex [x-y]

Los rangos de clases de caracteres no funcionan como se esperaba. Vea esta pregunta: ¿Por qué findtr no maneja 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 bytes (comúnmente considerado como el código ASCII, pero ASCII solo se define desde 0x00 – 0x7F). La mayoría de las implementaciones de expresiones regulares tratarían [A-Z] como todas las mayúsculas en mayúsculas en inglés. Pero FINDSTR usa una secuencia de clasificación que corresponde aproximadamente a cómo funciona SORT. Entonces [A-Z] incluye el alfabeto inglés completo, tanto en mayúsculas como en minúsculas (excepto “a”), así como caracteres alfabéticos no ingleses con 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 clases de caracteres regex. Los caracteres se representan como su valor de código de bytes 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 de EE. UU. 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 regex y ERROR

FINDSTR no solo está limitado a un máximo de 15 términos de clase de caracteres 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 indica “La utilidad Find String (QGREP) ha detectado un problema y debe cerrarse. Lamentamos 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 informado 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 bloquearse indefinidamente) si incluyen el código de bytes 0xFF (decimal 255)

Cualquier búsqueda de expresiones regulares que incluya el código de bytes 0xFF (decimal 255) fallará. Falla si el código de bytes 0xFF se incluye directamente o si se incluye implícitamente dentro de un rango de clases de caracteres. Recuerde que los rangos de clases de caracteres FINDSTR no clasifican caracteres en función del valor del código de bytes. Personaje <0xFF> aparece relativamente temprano en la secuencia de colación entre los <space> y <tab> caracteres. Entonces, cualquier rango de clase de personaje que incluya tanto <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 cuelga, pero siempre falla al 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

La expresión regular . El metacarácter solo debe coincidir con cualquier carácter que no sea <CR> o <LF>. Hay un error que le permite coincidir con el final del archivo si la última línea del archivo no termina con <CR> o <LF>. sin embargo, el . 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 se ha confirmado en XP y Win7.

Lo mismo parece ser cierto para los juegos de caracteres negativos. Algo como [^abc] coincidirá con el final del archivo. Conjuntos de caracteres positivos como [abc] parece funcionar bien. Solo lo he probado en Win7.

findstr a veces se cuelga inesperadamente al buscar archivos grandes.

No he confirmado las condiciones exactas ni 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. Esto parece que puede ser una variación de FINDSTR que se cuelga 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 es no redirigido.

La siguiente sesión de línea de comandos (Windows 7) demuestra cómo findstr puede colgarse al buscar un archivo de 3 GB.

C:DataTemp2014-04>echo 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890> T100B.txt

C:DataTemp2014-04>for /L %i in (1,1,10) do @type T100B.txt >> T1KB.txt

C:DataTemp2014-04>for /L %i in (1,1,1000) do @type T1KB.txt >> T1MB.txt

C:DataTemp2014-04>for /L %i in (1,1,1000) do @type T1MB.txt >> T1GB.txt

C:DataTemp2014-04>echo find this line>> T1GB.txt

C:DataTemp2014-04>copy T1GB.txt + T1GB.txt + T1GB.txt T3GB.txt
T1GB.txt
T1GB.txt
T1GB.txt
        1 file(s) copied.

C:DataTemp2014-04>dir
 Volume in drive C has no label.
 Volume Serial Number is D2B2-FFDF

 Directory of C:DataTemp2014-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:DataTemp2014-04>rem Findstr on the 1GB file does not hang

C:DataTemp2014-04>findstr "this" T1GB.txt
find this line

C:DataTemp2014-04>rem On the 3GB file, findstr hangs and must be aborted... even though it clearly reaches end of file

C:DataTemp2014-04>findstr "this" T3GB.txt
find this line
find this line
find this line
^C
C:DataTemp2014-04>

Tenga en cuenta que he verificado en un editor hexadecimal que todas las líneas terminan con CRLF. La única anomalía es que el archivo se termina con 0x1A debido a la forma copy obras. Sin embargo, tenga en cuenta que esta anomalía no causa problemas en archivos “pequeños”.

Con pruebas adicionales, he confirmado lo siguiente:

  • Utilizando copy con el /b opción para archivos binarios evita la adición de la 0x1A personaje, y findstr no se cuelga en el archivo de 3GB.
  • Terminar el archivo de 3GB con un carácter diferente también causa un findstr colgar.
  • los 0x1A El carácter no causa ningún problema en un archivo “pequeño”. (De manera similar para otros personajes de terminación).
  • Añadiendo CRLF después 0x1A resuelve el problema. (LF por sí solo probablemente sería suficiente).
  • Utilizando type para canalizar el archivo en findstr funciona sin colgar. (Esto puede deberse a un efecto secundario de type o | que inserta un final de línea adicional).
  • Usar entrada redirigida < también causa findstr colgar. Pero esto se espera; como se explica en la publicación de dbenham: “la entrada redirigida debe terminar en LF.
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *