Búsqueda desde una posición inicial hasta una final por cada línea de un archivo

Tengo un archivo que contiene muchísimas líneas casi 10.000. Se requiere que se produzca un segundo archivo con todas las líneas, que contienen un valor, ejem: "54654", pero que esté en la posición 11 a la 15 de la línea. Genere el código que busca a modo completo pero no se como adicionar el tema de búsqueda desde las posiciones indicadas. Este archivo no tiene limitadores ni separadores:

Archivo origen

Código

@echo ON
SET dia=%Date:~0,2%
SET mes=%Date:~3,2%
SET ano=%Date:~8,2%
SET var="54654"
PAUSE
CD /D D:\Perfil\
FOR /F "tokens=*" %%A in ('type "ORIGEN*"') do (ECHO %%A |findstr /I /P /L %var%) >>RECHAZADOS-%ano%%mes%%dia%.txt

Si se ejecuta me trae 3 líneas que contienen la cadena, pero yo necesito que solo traiga las líneas que contienen esa cadena en la posición indicada.

1 Respuesta

Respuesta
1

Prueba con esto:

@echo ON
Setlocal EnableDelayedExpansion
SET dia=%Date:~0,2%
SET mes=%Date:~3,2%
SET ano=%Date:~8,2%
SET var=54654
PAUSE
CD /D D:\Perfil\
FOR /F "tokens=*" %%A in ('type ORIGEN* ^|findstr /I /P /L %var%') DO (
set linea=%%A
if "!linea:~11,5!"=="%var%" echo !linea!>>RECHAZADOS-%ano%%mes%%dia%.txt
)

No sé bien para que usas "@echo ON" cuando lo normal suele ser "@echo OFF" pero eso no afecta al funcionamiento. Y le he quitado las comillas a la definición de la variable var porque creo que no aportan nada con FINDSTR. La posición 11 la interpreto, a partir del ejemplo, que empieza a numerar desde cero, pero si hubiera algún problema retoca ese valor

He seguido dándole vueltas al asunto, sobre todo a un aspecto que siempre me ha preocupado y nunca abordé en serio, la búsqueda con FINDSTR y expresiones regulares para posiciones que no son el inicio o el fin de la línea y creo que he encontrado una solución que se podría aplicar directamente si el número de caracteres de la línea es fijo. Supongamos que el archivo ORIGEN.TXT contiene lo siguiente:

0258igfjdojfds58465465y65465o65446454fdfdggfd
0258dffjdqo54654xdg54654654unaquesi454fdfdgfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258igfjdojfds5846546kk65465u465446454fdfdgfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258igfjdojfds5846lm54654465465446454fdfdggfd
0258igfjdojfds5846549546540651465446454fdfdgg
0258igfjdojfds58465465465465465446454fdfdggfd
0258dffjdop54654xdg546546dosquesi46454fdfdgfd
0258igfjdojfds584654665446545654465446454fdfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258dfgdfsg54654xdgfdsgfdgdasg4sdtresquesi46d

Ajustamos el patrón de lo buscado como se indica aquí:

0258igfjdojfds58465465y65465o65446454fdfdggfd
0258dffjdqo54654xdg54654654unaquesi454fdfdgfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258igfjdojfds5846546kk65465u465446454fdfdgfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258igfjdojfds5846lm54654465465446454fdfdggfd
0258igfjdojfds5846549546540651465446454fdfdgg
0258igfjdojfds58465465465465465446454fdfdggfd
0258dffjdop54654xdg546546dosquesi46454fdfdgfd
0258igfjdojfds584654665446545654465446454fdfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258dfgdfsg54654xdgfdsgfdgdasg4sdtresquesi46d
... 54654...

Y ahora copiamos el patrón en el comando de búsqueda directamente (junto con la incorporación de los datos de fecha al nombre del archivo que contiene las líneas seleccionadas):

type origen.txt | findstr ...........54654...........................>RECHAZADOS-%Date:~8,2%%Date:~3,2%%Date:~0,2%.txt

La ejecución directa de este último comando en una ventana CMD situada en la carpeta donde está el archivo ORIGEN.TXT creará el archivo buscado.

El editor de la página me alteró el patrón de la segunda ventana reduciendo el número de puntos a 3 por delante y tres por detrás cuando debería haber los puntos suficientes para alinear adecuadamente la cadena buscada en la posición correcta (como puede verse en la tercera ventana). Pero la idea creo que puede entenderse.

¡Gracias! gggirald!

El @echo ON lo deje para ver que pasaba cuando ejecutaba el .bat y así ver los posibles errores nada más. En este momento ya lo puedo cambiar a @echo OFF ya que gracias a lo que me indicaste funciono.

En la primera opción donde usas expresiones regulares, intente pero por alguna razón no me acciona el if, if "!línea:~10, 6!"=="%var%".

Entonces cuando finaliza muestra el archivo txt vacío.

Pero si realizo la segunda opción, me funciona perfectamente, esto ya que la longitud de cada línea es igual,

FOR /F "tokens=*" %%A  in ('type "ORIGEN*"')  do (ECHO %%A  |findstr ...........54654......................................... ) >>RECHAZADOS-%ano%%mes%%dia%.txt

Así que muchísimas gracias llevaba varios días realizando pruebas sin conseguir el resultado esperado. Excelente respuesta gggirald!... Gracias ! Gracias!

Me alegro mucho de haberte resuelto el problema.

Respecto a la primera opción, me da la impresión de que no has ajustado bien la posición inicial de la cadena ni la longitud de la misma. Si, como supongo, la imagen de la derecha muestra el archivo RECHAZADOS-170611.TXT, parece que la posición inicial debería ser la 11 y la longitud 5. De modo que el IF debería ser como el que figuraba en mi ejemplo y no como el que pones en tu texto, con posición inicial de 10 y longitud de 6. En todo caso, y a efectos de depurar el código, puedes incluir un echo antes del IF que saque precisamente la zona que estás controlando (algo como echo ! Línea:~10, 6!) Para ver si estás bien situada.

Otra vez el editor me ha hecho de las suyas. El echo que quería poner era

Echo ! Linea:~10,6!

Sin acento ni L mayúscula en "Línea" y sobre todo, sin separación entre la primera "!" y "Línea". A ver si ahora hay suerte y no cambia nada.

No la hubo. En fin espero que se entienda lo que quiero decir.

¡Gracias! Si entiendo lo que me indicas pero sigue apareciendo vacío intente de varias formas mira:

Al momento también estoy ensayando y buscando información por si se presenta una situación en el futuro donde las líneas no tengan longitud igual.

Gracias!

Prueba con esto. Copia y pega en un archivo de Bloc de notas o Notepad, no intentes reproducirlo a mano, ten en cuenta que la sintaxis multilínea de las instrucciones del DO de un FOR son un tanto peculiares:

@echo OFF
Setlocal EnableDelayedExpansion
SET dia=%Date:~0,2%
SET mes=%Date:~3,2%
SET ano=%Date:~8,2%
SET var=54654
PAUSE
CD /D D:\Perfil\
FOR /F "tokens=*" %%A in ('type ORIGEN* ^|findstr /I /P /L %var%') DO (
set linea=%%A
echo tramo revisado: !linea:~11,5!
if "!linea:~11,5!"=="%var%" echo !linea!>>RECHAZADOS-%ano%%mes%%dia%.txt
)

Si conseguimos que funcione ya veremos luego si se pueden dejar en una solo línea o no, en el caso de que tuvieras mucho interés en eso.

Perdón, si quieres usar el archivo DEVREC* en lugar de ORIGEN* para hacer las pruebas, eso sí que puedes cambiarlo.

¡Gracias! si es que utilizo varios archivos pero bueno hay no hay problema solo cambio el nombre... en esta ocasión al ejecutar se observa que el if si lo esta tomando en las posiciones indicadas, pero realiza la búsqueda sobre toda la linea, aunque el if ya comprobado que si lo esta ejecutando.

Veo que no has respetado exactamente la codificación que te pasé. La redirección hacia el archivo de salida:

>>RECHAZADOS-%ano%%mes%%dia%.txt

debe formar parte del IF:

if "!linea:~11,5!"=="%var%" echo !linea!>>RECHAZADOS-%ano%%mes%%dia%.txt

porque es la responsable de recoger el ECHO !LINEA!

Por otra parte el hecho de que salga algo como:

if "!linea:~11,5!"==""54654"" echo !linea!

con dobles comillas dobles antes y después del 54654, me indica que has dejado la instrucción:

SET var="54654"

en lugar de la que ponía yo:

SET var=54654

Esto impide que se cumpla la condición del IF y por tanto que no cumpla su función. En fin, que no me explico estas cosas.

Si tenias razón no estaba abarcando el if en su totalidad, pero si lo dejo literal como me indicas no me aparece nada de hecho se sale apenas realiza el for por eso no pude capturar la pantalla de cmd. 

la ruta real CD /D D:\Perfil\ es que en la imagen me quedo sin el \ al final.

Gracias

Vamos a ver si nos aclaramos y acordamos como hacer las pruebas para que los resultados sean comparables. Independientemente del editor que utilices para crear/editar el BAT quiero que respetes escrupulosamente la literalidad del BAT que te propongo. Además las pruebas vamos a hacerlas entrando en una ventana CMD y situándonos en la carpeta dónde esté el BAT (no ejecutando el BAT desde el explorador de Windows). Supongo que no tienes problemas para hacerlo (Ejecutar/CMD). Una vez allí, en primer lugar ejecuta los comandos (si, como parece, has llamado EJECUTAR.BAT al BAT en cuestión):

TYPE EJECUTAR.BAT

DEL RECHAZADOS-1706*.TXT

Luego ya teclea:

EJECUTAR

Una vez terminado el BAT (pulsando una tecla cuando lo pida el PAUSE) teclea:

TYPE RECH*.TXT

A continuación copia todo lo que haya en la ventana CMD (no hagas una captura por si no se viera todo). Si la ventana CMD no es suficientemente ancha (es decir, si tiene barra de desplazamiento horizontal) modifica su tamaño horizontal poniendo el ratón en la esquina inferior derecha y moviéndolo hacia la derecha. Una vez conseguido que no haya barra de desplazamiento horizontal te colocas en la parte superior y con el botón derecho del ratón fuerza que salga el menú contextual en el que eliges "Marcar". Con eso verás que el área que vas recorriendo se va marcando. Una vez que hayas marcado todo lo que interesa (que en este caso es todo) pulsa la tecla INTRO/ENTER/RETORNO. Esto es lo equivalente al Control-C y copia al portapapeles el contenido marcado. Ahora puedes ir a tu editor favorito y pulsar Control-V para pegar el texto copiado. Y también puedes copiarlo en una ventana de esta página eligiendo el botón que abre la ventana de Snippet (es el botón con icono <>, tercero por la derecha en la barra de herramientas de la página).

Una vez aclarado esto te diré que ninguno de los dos BAT que muestras en los dos pantallazos anteriores funcionará (a no ser que sea el editor el que parte las líneas). La sintaxis de los BAT es muy rigurosa y el DO tiene que estar en la misma línea del DO y el ECHO ! Linea! tiene que estar en la misma línea del IF. Te copio en un snippet toda una ejecución de un bat similar al tuyo (no uso el comando CD porque el archivo ORIGEN.TXT que utilizo está en la misma carpeta) para que puedas comprobar que me funciona:

C:\Users\g\Documents\BAT>del rech*.*
C:\Users\g\Documents\BAT>type rech*.*
El sistema no puede encontrar el archivo especificado.
C:\Users\g\Documents\BAT>type marmu.bat
@echo ON
rem @echo OFF
Setlocal EnableDelayedExpansion
SET dia=%Date:~0,2%
SET mes=%Date:~3,2%
SET ano=%Date:~8,2%
SET var=54654
PAUSE
rem CD /D D:\Perfil\
FOR /F "tokens=*" %%A in ('type ORIGEN* ^|findstr /I /P /L %var%') DO (
set linea=%%A
if "!linea:~11,5!"=="%var%" echo !linea!>>RECHAZADOS-%ano%%mes%%dia%.txt
)
C:\Users\g\Documents\BAT>type orig*.*
origen.txt
0258igfjdojfds58465465y65465o65446454fdfdggfd
0258dffjdqo54654xdg54654654unaquesi454fdfdgfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258igfjdojfds5846546kk65465u465446454fdfdgfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258igfjdojfds5846lm54654465465446454fdfdggfd
0258igfjdojfds5846549546540651465446454fdfdgg
0258igfjdojfds58465465465465465446454fdfdggfd
0258dffjdop54654xdg546546dosquesi46454fdfdgfd
0258igfjdojfds584654665446545654465446454fdfd
0258igfjdojfds58465465465465465446454fdfdggfd
0258dfgdfsg54654xdgfdsgfdgdasg4sdtresquesi46d
0258dfgdfsg54654xdgfdsgfdgdasg4sd6fg46d4g6df4gfgfdsgdgdg4
C:\Users\g\Documents\BAT>marmu
C:\Users\g\Documents\BAT>rem @echo OFF
C:\Users\g\Documents\BAT>Setlocal EnableDelayedExpansion
C:\Users\g\Documents\BAT>SET dia=13
C:\Users\g\Documents\BAT>SET mes=06
C:\Users\g\Documents\BAT>SET ano=17
C:\Users\g\Documents\BAT>SET var=54654
C:\Users\g\Documents\BAT>PAUSE
Presione una tecla para continuar . . .
C:\Users\g\Documents\BAT>rem CD /D D:\Perfil\
C:\Users\g\Documents\BAT>FOR /F "tokens=*" %A in ('type ORIGEN* |findstr /I /P /L 54654') DO (
set linea=%A
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
origen.txt
C:\Users\g\Documents\BAT>(
set linea=0258dffjdqo54654xdg54654654unaquesi454fdfdgfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258igfjdojfds58465465465465465446454fdfdggfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258igfjdojfds58465465465465465446454fdfdggfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258igfjdojfds5846lm54654465465446454fdfdggfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258igfjdojfds5846549546540651465446454fdfdgg
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258igfjdojfds58465465465465465446454fdfdggfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258dffjdop54654xdg546546dosquesi46454fdfdgfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258igfjdojfds58465465465465465446454fdfdggfd
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258dfgdfsg54654xdgfdsgfdgdasg4sdtresquesi46d
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>(
set linea=0258dfgdfsg54654xdgfdsgfdgdasg4sd6fg46d4g6df4gfgfdsgdgdg4
 if "!linea:~11,5!" == "54654" echo !linea! 1>>RECHAZADOS-170613.txt
)
C:\Users\g\Documents\BAT>type rech*.*
RECHAZADOS-170613.txt
0258dffjdqo54654xdg54654654unaquesi454fdfdgfd
0258dffjdop54654xdg546546dosquesi46454fdfdgfd
0258dfgdfsg54654xdgfdsgfdgdasg4sdtresquesi46d
0258dfgdfsg54654xdgfdsgfdgdasg4sd6fg46d4g6df4gfgfdsgdgdg4
C:\Users\g\Documents\BAT>del rech*.*
C:\Users\g\Documents\BAT>type marmu.bat
@echo ON
rem @echo OFF
Setlocal EnableDelayedExpansion
SET dia=%Date:~0,2%
SET mes=%Date:~3,2%
SET ano=%Date:~8,2%
SET var=54654
PAUSE
rem CD /D D:\Perfil\
FOR /F "tokens=*" %%A in ('type ORIGEN* ^|findstr /I /P /L %var%')
DO ( set linea=%%A
if "!linea:~11,5!"=="%var%"
echo !linea!>>RECHAZADOS-%ano%%mes%%dia%.txt)
C:\Users\g\Documents\BAT>marmu
C:\Users\g\Documents\BAT>rem @echo OFF
C:\Users\g\Documents\BAT>Setlocal EnableDelayedExpansion
C:\Users\g\Documents\BAT>SET dia=13
C:\Users\g\Documents\BAT>SET mes=06
C:\Users\g\Documents\BAT>SET ano=17
C:\Users\g\Documents\BAT>SET var=54654
C:\Users\g\Documents\BAT>PAUSE
Presione una tecla para continuar . . .
C:\Users\g\Documents\BAT>rem CD /D D:\Perfil\
La sintaxis del comando no es correcta.
C:\Users\g\Documents\BAT>FOR /F "tokens=*" %A in ('type ORIGEN* ^|findstr /I /P /L 54654')
C:\Users\g\Documents\BAT>type rech*.*
El sistema no puede encontrar el archivo especificado.
C:\Users\g\Documents\BAT>

Como puedes ver primero borro cualquier archivo preexistente cuyo nombre empiece por RECH y compruebo que no existe. Luego fuerzo la presentación del BAT, al que he llamado (en tu honor ;-)) MARMU.BAT para que pueda verse exacta y rigurosamente su aspecto y sintaxis. Luego fuerzo la presentación del ORIGEN.TXT que se utiliza en el BAT para que se vea que contiene registros variados. Luego ejecuto el MARMU. Como tiene el "@ECHO ON" van saliendo los comandos que se ejecutan. Cuando termina el BAT presento el RECH* para que pueda verse que se han escrito en él las líneas que interesaban. Luego presento una versión del MARMU.BAT con el aspecto aproximado del primero de tus pantallazos para que veas que al ir a ejecutarse el FOR sale un mensaje indicando que "La sintaxis del comando no es correcta".

Si quieres que lleguemos al fondo de este asunto intenta hacer lo que te sugiero y a partir de ahí podríamos profundizar en el análisis. ¡Suerte!

¡Gracias! 

Bueno hoy paso lo siguiente, cuando llegue a mi trabajo vi tu nota, realice paso a paso, (antes te comento el contexto , debo realizar este .bat el cual una malla lo ejecutara en un momento dado para que realice esa opción de filtro, esto pasa una vez al día, es decir yo dejo el .bat en una ruta y la malla se encarga de accionarlo allí. El ejecutable, esta en una ruta y el resultado de este es decir el .txt se debe generar en la misma ruta del archivo Origen o DEVREC) entonces realice paso a paso teniendo en cuenta hasta espacios absolutamente todo por la consola de CMD, pero el archivo RECHAZADOS siempre quedaba vació. así que seguí tal cual como pruebo estos .bat y la única forma que me ejecuto no dejar el for completo en una sola linea sino tal cual como lo vez en la imagen, y ademas con algunos ajustes como el (echo %%A) y que el archivo RECHAZADOS estuviera fuera del paréntesis del FOR... esto me funciono en mi equipo local donde realice la prueba y en el servidor donde debía instalar que en un server 2012 R2, las demás lineas de que observas son adicionales que debo colocar por cuestiones de log, (Pero igual sin estas funciona), ahora lo intento probar en mi equipo local de la casa y no me funciona la verdad no se que pensar si es cuestión de versiones o que, pero eso si te aseguro con el primer tipo de búsqueda que es secuencial : 

| findstr ...........54654...........................>RECHAZADOS-%Date:~8,2%%Date:~3,2%%Date:~0,2%.txt

el filtrado de ese archivo a procesar se demoro 12 horas literalmente (Así de pesado es), pero con la búsqueda directa que fue la segunda opción que me indicaste los ajustes que realice, se demoro 12 segundos.. así que menos mal salio, porque ya andaba algo preocupada. 

En todo caso muchas gracias por todo me queda la duda de si es por versiones que funciona de una forma en algunos sistemas y en otros de otra. Aquí seguiré tal vez con nuevas dudas ya que estoy iniciando en este mundo del batch.

Nota: por desgracia no pude adjuntar imágenes de todas las pruebas que realice hoy ya que las hice en el trabajo y por seguridad no puedo enviarlas al correo, esta es una replica de lo ejecutado que pude sacar, ya que era un borrador. lo único diferente son las rutas, nombres de archivos y variables.

Lo dejaremos así si, como parece, no hay posibilidad de avanzar en la averiguación de las causas del funcionamiento inesperado. Este BAT en sí es sencillo y no tiene grandes complicaciones. Creo que con un archivo de pruebas de pocas líneas se debería poder probar primero en un entorno acotado y luego ya "en malla" (supongo que quiere decir "en red") una vez que se haya comprobado el buen funcionamiento. En cuanto a las versiones de Windows, supongo que tendrás equipos con distintas versiones y bastaría probar el mismo batch, con los mismos pequeños archivos de prueba, en esas distintas versiones para ver si el resultado era o no diferente.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas