Buscar una cadena "PART_NAME=" si la encuentra saltar 2 lineas y sustituir PART_X_DIM=1990 si valor >600 en una carpeta completa

Recorrer una carpeta y en cada archivo buscar una cadena

"PART_NAME=""SCRAP"""
PART_ID=0
QUANTITY=1
PART_X_DIM=221
PART_Y_DIM=49

si encuentra la cadena "PART_NAME=""SCRAP""" salte 3 lineas y evalue si el valor de PART_X_DIM= es mayor de 600 reemplazarlo por 10

¿Es posible?

1 respuesta

Respuesta
1

Creo que sí que sería posible crear un bat para hacer lo que dices pero no me queda muy claro que se hace con las líneas que "se saltan". ¿Se dejan tal cual en el archivo de salida o se eliminan de ese archivo de salida?

El bat adjunto intentaría hacerlo pero dejando tal cual las líneas que se saltan. Es decir que solo modificaría la tercera línea siguiente a la que contiene la cadena "PART_NAME=""SCRAP""" en el sentido de cambiar el valor a 10 si fuera superior a 600. Las demás líneas las dejaría tal cual. El archivo de salida es el kkk.txt y una vez comprobado que la cosa funciona correctamente podría habilitarse la reescritura del archivo (eliminando el "rem" del penúltimo comando):

@echo off
Setlocal EnableDelayedExpansion
del /q kkk.txt
for /f "tokens=* delims=" %%a in ('dir /b') do (findstr /C:"\"PART_NAME=\"\"SCRAP\"\"\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
set ind=N
set /a cont=0
echo Tratando archivo %~1
for /f "tokens=* delims=" %%x in ('type "%~1"') do (
   set lin=%%x
   if #%%x#==#"PART_NAME=""SCRAP"""# set ind=S
   if !ind!==S set /a cont+=1
   if !ind!==N echo %%x>>kkk.txt
   if !ind!==S if !cont! neq 4 echo %%x>>kkk.txt
   if !cont! equ 4 if !lin:~11! gtr 600 echo PART_X_DIM=10>>kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

He puesto un pause en la rutinilla de tratamiento para poder ir archivo a archivo revisando el kkk.txt para ver si se está haciendo bien.

Como el editor de la página introduce con frecuencia espacios entre el carácter "!" y el nombre de la variable habrá que tener eso en cuenta para corregirlo. Nunca debe haber un espacio entre "!" y el nombre de la variable.

Ya me contarás como va.

He visto un errorcillo y, de paso, he mejorado ligeramente una cosa. Así sería como debe ser:

@echo off
Setlocal EnableDelayedExpansion
del /q kkk.txt
for /f "tokens=* delims=" %%a in ('dir /b') do (findstr /C:"\"PART_NAME=\"\"SCRAP\"\"\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
set ind=N
set /a cont=0
echo Tratando archivo %~1
for /f "tokens=* delims=" %%x in ('type "%~1"') do (
   set lin=%%x
   if #%%x#==#"PART_NAME=""SCRAP"""# set ind=S
   if !ind!==S set /a cont+=1
   if !cont! neq 4 echo %%x>>kkk.txt
   if !cont! equ 4 if !lin:~11! gtr 600 echo PART_X_DIM=10>>kkk.txt
   if !cont! equ 4 if !lin:~11! lss 600 echo %%x>>kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

Otro error. En vez de "lss" debe ponerse "leq" para que no se escape el valor 600 (las líneas con ese valor no se pasarían al archivo de salida)

¡Gracias!

Mil gracias voy a probar y te cuento me has ayudado muchísimo, sabes sin intentar abusar pregunto es posible usar sentencia or es decir si una de las líneas PART_X_DIM o PART_Y_DIM es mayor de 600 que cambie ADDRESS=10 y deje sin modificar las dos que evalúa, solo lo debe evaluar si el párrafo contiene PART_NAME="SCRAP", ejemplo para este primer párrafo no debe evaluar ni cambiar porque PART_NAME no es igual a SCRAP y siempre dentro del archivo donde los valores a evaluar están 3 y 4 líneas más abajo eso no cambia. Y valor a cambiar está 6 líneas abajo de donde encuentra la línea SCRAP

PART_DATA=4
PART_NAME="2180425 Esp10_012"
PART_ID=1
QUANTITY=1
PART_X_DIM=533
PART_Y_DIM=105
ANGLE=0
ADDRESS=2
SAVE_DATA
PART_DATA=5
PART_NAME="SCRAP"
PART_ID=0
QUANTITY=1
PART_X_DIM=533
PART_Y_DIM=46
ANGLE=0
ADDRESS=1
SAVE_DATA

Saludos si necesitas que te envíe un archivo completo me dices

Gracias

Antes de nada quiero corregir el bat, porque había entendido, erróneamente por lo que veo, que la línea significativa a buscar era

"PART_NAME=""SCRAP"""

y ahora veo que es

PART_NAME="SCRAP"

Para lo otro que dices (posibilidad de usar un "or") me parece entender ahora que cuando se detecte la línea buscada (PART_NAME="SCRAP") se deben controlar los valores de las líneas 3ª (PART_X_DIM) y 4ª (PART_Y_DIM) posteriores a ella y si el valor de alguna de ellas es superior a 600 se modifique la línea 6ª pero respetando tanto la línea 3ª como la 4ª. En resumen que el archivo de salida es idéntico al de entrada salvo en los casos en que la 3ª o 4ª línea que sigue a una PART_NAME="SCRAP" tengan valores superiores a 600, en cuyo caso la línea 6ª (ADDRESS) se cambiará a valor 10 dejando todo lo demás igual que estaba.

Si es así este es el bat que creo que lo haría:

@echo off
Setlocal EnableDelayedExpansion
del /q kkk.txt
for /f "tokens=* delims=" %%a in ('dir /b') do (findstr /C:"PART_NAME=\"SCRAP\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
set ind=N
set mod=N
set /a cont=0
echo Tratando archivo %~1
for /f "tokens=* delims=" %%x in ('type "%~1"') do (
   set lin=%%x
   if #%%x#==#PART_NAME="SCRAP"# set ind=S
   if !ind!==S set /a cont+=1
   if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
   if !cont! equ 5 if !lin:~11! gtr 600 set mod=S
   if !cont! neq 7 echo %%x>>kkk.txt
   if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt
   if !cont! equ 7 if !mod!==N echo %%x>>kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

Pruébalo y me dices.

Ya me lo hace en el archivo kkk.txt, solo una cosa me inserta una línea ECHO est desactivado. Después de cambiar a 10 el address y cuando eliminino pause y rem no guarda los cambios en el mismo archivo, ¿sabes qué puede ser?

Gracias

No lo sé. Ahora tengo que irme. Pásame el archivo porque ya pueden ser detalles concretos porque en mis pruebas no me falla ni me sale el mensaje "ECHO est desactivado" (mensaje típico de hacer ECHO a una línea en blanco)


gggirald ya resolví lo de la línea del echo, una ultima ayuda por favor, no encuentro que contador debo reiniciar para que lo haga hasta fin de archivo y no solo una vez como ahora lo hace

Gracias

Tienes razón. Hay que reiniciar el contador y los indicadores una vez que se han utilizado.

Prueba cambiando esta línea:

   if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt

por esta:

   if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt&set /a cont=0&set ind=N&set mod=N

Creo que hay que cambiar las dos:

   if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt&set /a cont=0&set ind=N&set mod=N
   if !cont! equ 7 if !mod!==N echo %%x>>kkk.txt&set /a cont=0&set ind=N&set mod=N

Por cierto, ¿ya te funciona la reescritura del archivo original al quitar el "rem"?

¡Gracias!

Si me funciona lo de la escritura con esa asignación de variables me ayudas mucho, seguiro probando hasta lograrlo

Muchas gracias!

Girald al final me funciono asi

if #%%x#==#PART_NAME="SCRAP"# set ind=S&set /a cont=0
if !ind!==S set /a cont+=1
if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
if !cont! equ 5 if !lin:~11! gtr 600 set mod=S
if !cont! neq 7 echo %%x>>kkk.txt
if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt
if !cont! equ 7 if !mod!==N echo %%x>>kkk.txt
if !cont! equ 7 if !mod!==S set mod=N& set /a cont=0

pero no hago que pase estas lineas al kkk.txt

%_N_H2180425E10003_MPF
;$PATH=/_N_WKS_DIR/_N_WORK_1_WPD
; SEP 03 2018 12:03:44
;*MODEL SG-840D-2007 

sera por los caracteres especiales que lee al principio?

puedo usar algun caracter especial como ^' o algo similar?

La razón de este comportamiento es que el valor por defecto del parámetro EOL ("end of line") del comando FOR es precisamente ";". Eso hace que el FOR no tenga en cuenta las líneas que empiezan por ";". Para resolverlo solo tienes que cambiar la línea:

for /f "tokens=* delims=" %%x in ('type "%~1"') do (

por esta otra:

for /f "tokens=* eol= delims=" %%x in ('type "%~1"') do (

Aprovecho para decirte que para insertar código resulta más legible (y más manejable, creo yo) utilizar la opción "<>" (SNIPPET) de las herramientas de la página.

¡Gracias!

Ah gracias por el dato del snippet, me va muy bien la rutina, ¿sabes cómo hacer que incluso copie los saltos de lines para dejar el archivo con mismo numero de líneas? Y tengo así mi línea

for /f "tokens=* eol= delims=" %%a in ('dir /b "g:\cn files\*.NC"')

en esta linea uso una ruta fija pero quiero lo haga en cualquier carpeta intente con 

"*.NC"

pero no me funciona, ¿saber cómo debo escribir el comando?

El tema de respetar las líneas en blanco es el talón de Aquiles de estas rutinas. Normalmente se puede hacer pero complica bastante la cosa. Intentaré adaptar el procedimiento que he usado alguna vez a este caso y seguramente te digo algo en un rato.

Respecto a que se aplique el procedimiento a todos los archivos con extensión NC con independencia de la carpeta en la que estén, pero en la unidad G:, creo que se puede conseguir con

dir /b /s g:*.NC

En todo caso prueba directamente el comando, con las variantes que se te ocurran, desde una ventana CMD antes de decidir el que vayas a poner en el FOR

¡Gracias!

De acuerdo haré pruebas, aunque ya eso de la líneas en blanco no es tan importante

Mil gracias Girald

Creo que ya lo tengo (lo de respetar las líneas en blanco). Por lo que intuyo que has hecho hasta ahora tendrás que adaptar mi solución porque creo que no la aplicas tal cual. He cambiado el borrado del kkk.txt al ámbito de la rutina TRATARCH porque me he dado cuenta de que era ahí dónde debía estar. Así es como me ha quedado:

@echo off
Setlocal EnableDelayedExpansion
for /f "tokens=* delims=" %%a in ('dir /b /s g:*.NC') do (findstr /C:"PART_NAME=\"SCRAP\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
del /q kkk.txt
echo.> temp.txt
set ind=N
set mod=N
echo Tratando archivo %~1
for /f "skip=2 eol= tokens=1*" %%x in ('fc /LB1000 /n temp.txt "%~1" ^| findstr -v "*****"') do (
   if not "%%y" == "" (
      set lin=%%y
      if #%%y#==#PART_NAME="SCRAP"# set ind=S&set /a cont=0
      if !ind!==S set /a cont+=1
      if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
      if !cont! equ 5 if !lin:~11! gtr 600 set mod=S
      if !cont! neq 7 echo %%y>>kkk.txt
      if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt&set ind=N&set mod=N
      if !cont! equ 7 if !mod!==N echo %%y>>kkk.txt&set ind=N
      )
   if "%%y" == "" echo.>> kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

El parámetro LB del comando FC debe ajustarse para que sea superior al número de líneas de los archivos a tratar, pero cuanto mayor sea más tardará el comando en ejecutarse, por lo que no procede exagerar mucho.

A ver si hay suerte y funciona bien en todos los aspectos. Yo he hecho alguna pruebecilla con buen resultado pero mi archivo de pruebas es limitado.

veo usas x

"skip=2 eol= tokens=1*" %%x in 

y luego usas 'y'

  set lin=%%y

 es correcto asi o deberia ser ambas "y" ?

Es correcto. En eso consiste el truco para las líneas en blanco. El comando FC /N al comparar un archivo en blanco (el TEMP.TXT) con otro saca en primer lugar el número de línea (que pasaría a la variable %%x) y en segundo lugar el contenido de la línea (que pasaría a la variable %%y)

Por cierto que he visto un error. Hay que invertir las líneas:

      if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt&set ind=N&set mod=N
      if !cont! equ 7 if !mod!==N echo %%y>>kkk.txt&set ind=N

para que queden así:

      if !cont! equ 7 if !mod!==N echo %%y>>kkk.txt&set ind=N
      if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt&set ind=N&set mod=N
@echo off
Setlocal EnableDelayedExpansion
for /f "tokens=* eol= delims=" %%a in ('dir /b "g:\cn files\*.NC"') do (findstr /C:"PART_NAME=\"SCRAP\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
del /q kkk.txt
set ind=N
set mod=N
set /a cont=0
echo limpiando archivo %~1
for /f "tokens=* eol= delims=" %%x in ('type "%~1"') do (
   set lin=%%x
   if #%%x#==#PART_NAME="SCRAP"# set ind=S&set /a cont=0
   if !ind!==S set /a cont+=1
   if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
   if !cont! equ 5 if !lin:~11! gtr 600 set mod=S
   if !cont! neq 7 echo %%x>>kkk.txt
   if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt
   if !cont! equ 7 if !mod!==N echo %%x>>kkk.txt
   if !cont! equ 7 if !mod!==S set mod=N& set /a cont=0
)
pause
rem copy /y kkk.txt %~1
goto :eof

este si me funciona pero sin lo de las lineas en blanco, ya hice pruebas con el ultimo codigo que me enviaste pero estoy revisando por que se sale sin crear nada

gracias

Yo no pondría "eol=" en el primer FOR porque ahí nos da igual que lo considere fin de línea porque la cadena que buscamos no va a estar en una línea que empiece por ";", aunque tampoco estorba.

Lo que no me encaja es que no se "limpie" la variable MOD (de "modificar") después de haber sido usada. Tal como yo lo veo si en alguna 3ª o 4ª línea posterior a la cadena buscada el valor correspondiente supera 600 ya en todas las ocurrencias de esa cadena se va a aplicar el ADDRESS=10.

Y no entiendo que salga sin crear nada. Copia, si quieres, el BAT tal como lo tienes a ver si a mí también me ocurre y, si fuera así, intentaría averiguar la causa.

@echo off
Setlocal EnableDelayedExpansion
del /q kkk.txt
for /f "tokens=* delims=" %%a in ('dir /b "G:\cn files\*.NC"') do (findstr /C:"PART_NAME=\"SCRAP\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
echo.> temp.txt
set ind=N
set mod=N
set /a cont=0
echo limpiando archivo %~1
for /f "skip=2 eol= tokens=1*" %%x in ('fc /LB5000 /n temp.txt "%~1" ^| findstr -v "*****"') do (
   if not "%%y" == "" (
     set lin=%%y
     if #%%y#==#PART_NAME="SCRAP"# set ind=S&set /a cont=0
     if !ind!==S set /a cont+=1
     if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
     if !cont! equ 5 if !lin:~11! gtr 600 set mod=S
     if !cont! neq 7 echo %%y>>kkk.txt
     if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt
     if !cont! equ 7 if !mod!==N echo %%y>>kkk.txt
     if !cont! equ 7 if !mod!==S set mod=N& set /a cont=0
   if "%%y" == "" echo.>> kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

Este es el que no me funciona y si tienes razón ya habia eliminado el eol de primer for

no quiero molestarte demasiado si no puedes hacerlo por tiempo ya luego lo vemos

te agradezco 

Antes de hacer ninguna prueba he visto que falta el paréntesis de cierre del

if not "%%y" == "" (

que debería estar antes del

  if "%%y" == "" echo.>> kkk.txt

Mira a ver si esto lo explica.

Toda la razón Girald, buen día, sabes cuando evalúa esta línea

     if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
     if !cont! equ 5 if !lin:~11! gtr 600 set mod=S

no elimina los espacios al final de la linea y ya trate con 

     if !cont! equ 4 if !%%lin:~11! gtr 600 set mod=S
     if !cont! equ 5 if !%%lin:~11! gtr 600 set mod=S

pero sigue sin eliminar los espacios entonces cuando evalua si es mayor lo ignora por llevar un espacio al final y no modifica la variable a mod=S, que puede ser?

Ya lo hice con estas líneas

 set lin=%%y
 lin=%lin:=%

igualmente te agradezco toda la ayuda

Empezaré por aclararte algunas cosas. El uso de %% delante de las variables implícitas de los bucles FOR dentro de un BAT es una forma de "escapar" el carácter especial del "%" de las variables. En un FOR directo (no incluido en un BAT) las variables implícitas solo van precedidas de un %.

Por tanto no tiene ningún sentido usar %% delante de una variable que no sea una variable implícita de un bucle FOR. Las variables internas de un BAT se invocan siguiendo el esquema %var%, que se convierte en !var! Cuando se ha utilizado previamente el comando "Setlocal EnableDelayedExpansion". El uso de !var! En lugar de %var% es necesario cuando el valor de la variable VAR se puede alterar dentro de un bucle FOR.

Mientras escribía lo anterior he visto que te me has adelantado y has dado con la clave para eliminar los espacios dentro del contenido de una variable. Yo te hubiera dicho que usaras

set lin=!lin: =!

en vez de

set lin=%lin: =%

Pero tal vez lo que te digo más arriba no sea necesario en el caso de las propias variables implícitas del bucle FOR (como lo son %%x, %%y, etc.)

¿Cómo queda la cosa ahora? ¿Ya está todo en orden?

Tengo pendiente de aclarar lo que te comentaba respecto a la variable MOD en mi penúltimo mensaje del día 7.

Fíjate que algo bien curioso en realidad no me esta elimiando el espacio del final de línea

set lin=!lin: =!

lo escribo asi y no pasa nada, sera que estoy usando mal la sintaxis?

  set lin=%%y
  set lin=!lin: =!

Perdon fue un error en la asignacion de variables asi me funciona perfecto

gracias

Respondo para no dejar la pregunta pendiente de respuesta. Si ya todo te funciona como necesitabas no es necesario que digas nada más. Pero si hay algo pendiente podemos seguir con este hilo.

Buenos días estoy intentando evaluar parte de una línea pero no me reconoce la sintaxis

     if #%%y#==#PART_NAME="SCRAP"# set ind=S&set /a cont=0
     if %y:~0,9%==#PART_DATA=# set ind=S&set /a cont=1 % set mod=S

es la segunda linea me da error que no esperaraba 9

En primer lugar no hay, que yo sepa, forma de aplicar directamente la sintaxis que permite extraer parte de una cadena a las variables internas de un FOR. Esa era la razón por la que creaba una variable LIN para poder aplicarle ese procedimiento. La sintaxis %y:~0,9% se aplicaría a una variable "y" definida mediante un SET Y=... pero la variable a la que la pretendes aplicar es una variable interna de un FOR. Ten en cuenta que las variables definidas con SET se "invocan" entre %% pero las internas de un FOR lo hacen "precedidas" de %%. Se me acaba de ocurrir que, si estuviera permitido, tendría que ser algo como %%y:~0,9%% pero lo he probado y no sirve.

En segundo lugar el papel de los caracteres que "envuelven" a las variables o literales en un IF (en este caso los caracteres # pero pueden ser cualquiera) es el de evitar algunos problemas si la variable puede estar vacía. Pero siempre hay que ponerlos a ambos lados de la comparación, aunque esto seguramente no daría error de sintaxis. Por tanto deberías haber puesto algo como

if #%y:~0,9%#==#PART_DATA=#

Por último creo que has puesto un % en lugar de un & al final de la línea, precediendo a "set mod=S"

Gracias Giral por la explicación y la corrección del % en lugar del &. Hice varias pruebas y siempre me genera error que no es epera el 9, ¿se podrá usar de otra forma el numero de caracteres que debe leer?

Cuéntame un poco que es lo que quieres hacer ahora, porque supongo que es distinto de lo que ya habíamos conseguido, creo. Y, si quieres, aporta el bat completo de tu último intento

Estoy intentando adicionar un if que evalúe parte de la cadena de una línea, y si cumple que setee valores a variables que modifican la línea ADRESS

@echo off
Setlocal EnableDelayedExpansion
for /f "tokens=* delims=" %%a in ('dir /b "d:\cn files\*.NC"') do (findstr /C:"PART_NAME=\"SCRAP\"" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
del /q kkk.txt
echo.> temp.txt
set ind=N
set mod=N
set /a cont=0
echo limpiando archivo %~1
for /f "skip=2 eol= tokens=1*" %%x in ('fc /LB5000 /n temp.txt "%~1" ^| findstr -v "*****"') do (
   if not "%%y" == "" (
     set lin=%%y
     set lin=!lin: =!
     if #%%y#==#PART_NAME="SCRAP"# set ind=S&set /a cont=0
     if #%y:~0,9%#==#PART_DATA# set ind=S&set /a cont=1 & set mod=S
     if !ind!==S set /a cont+=1
     if !cont! equ 4 if !lin:~11! gtr 600 set mod=S
     if !cont! equ 5 if !lin:~11! gtr 600 set mod=S
     if !cont! neq 7 echo %%y>>kkk.txt
     if !cont! equ 7 if !mod!==S echo ADDRESS=10>>kkk.txt
     if !cont! equ 7 if !mod!==N echo %%y>>kkk.txt
     if !cont! equ 7 if !mod!==S set mod=N& set /a cont=0   
     )
   if "%%y" == ""  echo.>> kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

Asi es como lo tengo escrito pero salta el error que no espera 9 se que es por lo que mencionas de como lee las variables dentro de un FOR, pero ya hice varios intentos y no lo consigo. y si esto es algo diferente de lo que ya habia logrado, es decir, agregar un if adicional para que evalue parte de una cadena.

Pero en la información que yo tengo del archivo de partida PART_DATA no forma parte de las líneas que contienen PART_NAME="SCRAP" así que tendrás que pasarme un ejemplo real de esas líneas. Ten en cuenta que tal como está el BAT va buscando ese contenido en todos los archivos y si lo encuentra en uno lo pasa a la rutina interna que empieza a leerlo línea a línea. A mí me da la impresión de que quieres tratar una línea diferente, no la que contiene PART_NAME="SCRAP". Se puede hacer claro, pero supongo que entonces el tratamiento será diferente, ¿o no?

Ahora voy entiendo un poco más el código, es decir, en la primera línea del findstr le dices si PART_NAME = "SCRAP"

PART_DATA=2
PART_NAME="SCRAP"
PART_ID=0
QUANTITY=1
PART_X_DIM=388
PART_Y_DIM=688 
ANGLE=0 
ADDRESS=2
SAVE_DATA
PART_DATA=3
PART_NAME="Dibujo1_015"
PART_ID=1
QUANTITY=4
PART_X_DIM=592
PART_Y_DIM=1121
ANGLE=0 
ADDRESS=2
SAVE_DATA

Quiere decir que la unica manera es dar los paramatros de busqueda de multiples cadenas en el findstr y quiero entender entonces, el primer for es solo para saber si dentro del archivo que leo existe PART_NAME="SCRAP" y si existe entonces llamar la funcion tratartch que hace el resto del codigo, gracias

Eso es, básicamente. Intuyo que quieres hacer un tratamiento también cuando en algún archivo exista la cadena "PART_DATA=". Pero parece ser que esta condición es más restrictiva que la otra (la de que exista la cadena PART_NAME="SCRAP" en ese archivo) porque esta última siempre va precedida de la primera. Entonces yo diría que siempre que exista "PART_DATA=" en un archivo hay que hacer un tratamiento. Luego vendría distinguir los casos en que además de PART_DATA exista (en la línea siguiente) la otra cadena de los que no sea ese el caso y aplicar el tratamiento a cada caso. Puedes usar el ejemplo anterior para decirme que habría que hacer en cada uno de esos dos casos.

Si es más restrictiva si te refieres a que no busca toda la línea sino parte de ella, sera que puedo usar en el parámetro tokens 0-¿9 para delimitar la búsqueda?

En realidad creo que debería haber dicho "menos restrictiva" en lugar de lo contrario (¡Qué cabeza la mía!). En todo caso lo que quiero decir es que hay muchas más líneas que contienen esta otra cadena "PART_DATA=" que la otra cadena PART_NAME="SCRAP". Además cuando se da esta segunda siempre ocurre que en la línea anterior se dio la primera.

Y no, no quería decir nada relacionado con el tokens del FOR, lo cual no quiere decir que no sea posible usarlo aunque ahora no se me ocurra cómo.

Digamos por ejemplo, que cambiamos la cadena del primer FOR a "PART_DATA=" y sometemos a tratamiento (tratarch) a cualquier archivo en el que aparezca. En el tratamiento de archivo lo leemos línea a línea y revisamos si los 10 primeros caracteres de la línea son PART_DATA= (no sobre la variable propia del FOR sino sobre la variable LIN que hemos cargado previamente con el contenido de la línea, como hacía en el BAT anterior). Si se da ese caso activamos un indicador, por ejemplo IPD (de indicador de part_data), ponemos el contador relativo de líneas a cero y seguimos tratando líneas. A partir de aquí el procedimiento sería similar pero los valores de las cuentas de líneas se incrementarían en uno y el tratamiento podría ser diferente según estuvieran activos los dos indicadores o solo uno. Eso si el diferente tratamiento afectara a los mismos valores y líneas.

Pero creo que lo esencial es trabajar sobre un ejemplo concreto y lo más significativo posible, como te sugería en mi anterior mensaje.

Girald antes que nada gracias por seguir ayudándome

Antes que nada creo que si partimos de lo que mencionas de evaluar en el IF con LIN dentro del FOR he probado y no lo consigo te muestro como lo estoy haciendo

@echo off
Setlocal EnableDelayedExpansion
for /F "tokens=* delims=" %%a in ('dir /b "d:\cn files\*.NC"') do (findstr /C:"PART_DATA" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
del /q kkk.txt
echo.> temp.txt
set ind=N
set mod=N
set /a cont=0
echo limpiando archivo %~1
for /f "skip=2 eol= tokens=1*" %%x in ('fc /LB5000 /n temp.txt "%~1" ^| findstr -v "*****"') do (
   if not "%%y" == "" (
     set lin=%%y
     set lin=!lin: =!
     if #%y:~0-9%# ==#PART_DATA# set mod=S&set ind=S&set /a cont=0
     if !ind!==S set /a cont+=1
     if !cont! neq 8 echo %%y>>kkk.txt
     if !cont! equ 8 if !mod!==S echo ADDRESS=10>>kkk.txt
     if !cont! equ 8 if !mod!==N echo %%y>>kkk.txt
     if !cont! equ 8 if !mod!==S set mod=N& set /a cont=0   
     )
   if "%%y" == ""  echo.>> kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

siempre me salta error que no espera 9 de la linea de #%y:~0,9%# no soy capaz de encontrar el error de sintaxis creo

Es que no conseguí que entendieras la primera parte de mi explicación del 13 de septiembre. La línea

     if #%y:~0-9%# ==#PART_DATA# set mod=S&set ind=S&set /a cont=0

no tiene sentido. No se puede aplicar la sintaxis de extracción parcial de caracteres a una variable de un FOR. Aunque luego, al final de ese mensaje del 13 de septiembre, te corrigiera esa sintaxis como ejemplo del uso de los delimitadores "#" suponía que ya te había quedado claro que eso solo valdría si "y" era una variable normal y no una variable implícita de un FOR.

Tu bat tendría que ser algo como:

@echo off
Setlocal EnableDelayedExpansion
for /F "tokens=* delims=" %%a in ('dir /b "d:\cn files\*.NC"') do (findstr /C:"PART_DATA" "%%a">nul&&call :tratarch "%%a")
goto :eof
:tratarch
del /q kkk.txt
echo.> temp.txt
set ind=N
set mod=N
set /a cont=0
echo limpiando archivo %~1
for /f "skip=2 eol= tokens=1*" %%x in ('fc /LB5000 /n temp.txt "%~1" ^| findstr -v "*****"') do (
   if not "%%y" == "" (
     set lin=%%y
     set lin=!lin: =!
     if #!lin:~0-9!# ==#PART_DATA# set mod=S&set ind=S&set /a cont=0
     if !ind!==S set /a cont+=1
     if !cont! neq 8 echo %%y>>kkk.txt
     if !cont! equ 8 if !mod!==S echo ADDRESS=10>>kkk.txt
     if !cont! equ 8 if !mod!==N echo %%y>>kkk.txt
     if !cont! equ 8 if !mod!==S set mod=N& set /a cont=0   
     )
   if "%%y" == ""  echo.>> kkk.txt
)
pause
rem copy /y kkk.txt %~1
goto :eof

pero ese bat no hace nada porque la variable MOD no se cambia en ninguna línea. Pero verás como ahora no te da error de sintaxis y ya puedes empezar a pensar en el tratamiento.

Y cuando no entiendas algo de lo que te digo creo que es más útil que me lo preguntes, al menos después de algún intento de adivinación ;-))

Si comprendí mal cuando me dijiste que debería haber puesto algo como if #%y:~0, 9%#==#PART_DATA=#, pero bueno de momento estoy probando y si, la variable MOD la dejé que cambie al momento de comparar el problema es que valida esa línea pero no encuentra coincidencia, pero seguiré viendo que más puede ser, agradezco tu ayuda, en realidad si había evitado no me saltara el error pero sigo igual porque con esa sintaxis no salta el error pero tampoco valida y asigna los valores que corresponden. Pero como te digo seguiré viendo donde esta mi fallo

Saludos

Acabo de ver que tienes razón y que si que estaba previsto cambiar la variable MOD. Eso me ha llevado a repetir las pruebas y he encontrado un error o errata. No es !lin:~0-9! Lo que deberíamos poner sino !lin:~0,9! No lo noté en tu mensaje y se quedó ahí. Pero al ponerlo bien resulta que el IF no tolera tanta complicación en la sintaxis (manías de los BAT) y hay que sacarla del IF.

No sé si hemos superado la longitud permitida a una consulta (me ha pasado otras veces) pero no consigo que me acepte un nuevo snippet. De modo que lo hará a pelo

Prueba a cambiar esto:

     if #!lin:~0-9!# ==#PART_DATA# set mod=S&set ind=S&set /a cont=0

Por esto:

     set lin=!lin:~0,9!
     if #!lin!#    ==#PART_DATA# set mod=S&set ind=S&set /a cont=0

Y ten presente que el puñetero editor de la página puede que meta espacios indebidos entre "!" y "lin"

set lin=!lin:~0,9!
if #!lin!# ==#PART_DATA# set mod=S&set ind=S&set /a cont=0

asi lo deje como dijiste y es cierto este lenguaje no soporta tanto en su sintaxis, asi me funciona

Gracias Girald por tomarte el tiempo de contestar

Veo que tú no has tenido problemas para incluir un snippet. Si ya todo está a tu gusto damos por cerrado este asunto. Si tienes alguna otra duda podemos seguir por aquí o abrir otra pregunta.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas