Lote: evitar conflictos específicos en bucles FOR

Lote: evitar conflictos específicos en bucles FOR

Problema: comportamiento inesperado (duplicado único) en el bucle FOR.

Estoy intentando crear una interfaz vbscript por lotes sencilla para montar y desmontar volúmenes, entre otras tareas ("Voltask"). Una parte central de la función es la identificación única de cada volumen, lo que intento lograr analizando la salida de MOUNTVOL:

\\?\Volume{d35e9775-0176-11d6-a06d-806e6f6e6963}\
    H:\
\\?\Volume{d35e9776-0176-11d6-a06d-806e6f6e6963}\
    F:\
\\?\Volume{6537febd-01bc-11d6-adb5-806e6f6e6963}\
    *** NO MOUNT POINTS ***
\\?\Volume{3fb54500-a257-11e4-8d8d-806e6f6e6963}\
    *** NO MOUNT POINTS ***
\\?\Volume{6537febe-01bc-11d6-adb5-806e6f6e6963}\
    C:\
\\?\Volume{6537fec3-01bc-11d6-adb5-806e6f6e6963}\
    A:\
\\?\Volume{6537fec1-01bc-11d6-adb5-806e6f6e6963}\
    D:\
\\?\Volume{6537fec2-01bc-11d6-adb5-806e6f6e6963}\
    E:\

El primer análisis proporciona a algunas subrutinas lo que necesitan y, en general, hace que los datos sean más agradables de manejar. Cada línea relevante de MOUNTVOL se almacena en un número variable separado.

@ECHO OFF & SETLOCAL enabledelayedexpansion & SET count=0
REM Basic parse
FOR /F "usebackq" %%5 IN (`
MOUNTVOL ^| FINDSTR /c:\ /c:*
`) DO (
SET /a count+=1
SET !count!=%%5
)

El siguiente paso es tomar este resultado simple y acercarse un paso más a la combinación de las letras y nombres correspondientes: 1 2 3 4 5 -> 11 12 21 22 31... De esta manera, el primer número siempre representaría un volumen y el último el tipo de dato correspondiente al volumen, 1=nombre, 2=letra.

Estoy tratando de lograr esto analizando los datos obtenidos previamente con:

FOR /L %%G IN (1,1,%count%) DO (
SET /a ODD=%%G %%2
IF !ODD! EQU 1 (
SET A=%%G
SET /a A-=!C!
SET /a C+=1
SET B=1
) 
REM Intentionally not using "ELSE"
IF !ODD! EQU 0 (
SET A=%%G
SET /a A-=!C!
SET /a B+=1
)
SET !A!!B!=!%%G!
ECHO !A!!B! Has Data !%%G!
)

Solo para aclarar la aritmética: los conteos dan como resultado que A aumente cada segundo recorrido y B varíe entre 1 y 2.

La salida resultante tal como se muestra es:

11 Has Data \\?\Volume{d35e9775-0176-11d6-a06d-806e6f6e6963}\
12 Has Data H:\
21 Has Data \\?\Volume{d35e9776-0176-11d6-a06d-806e6f6e6963}\
22 Has Data F:\
31 Has Data \\?\Volume{6537febd-01bc-11d6-adb5-806e6f6e6963}\
32 Has Data ***
41 Has Data \\?\Volume{3fb54500-a257-11e4-8d8d-806e6f6e6963}\
42 Has Data ***
51 Has Data \\?\Volume{6537febe-01bc-11d6-adb5-806e6f6e6963}\
52 Has Data C:\
61 Has Data \\?\Volume{d35e9775-0176-11d6-a06d-806e6f6e6963}\
62 Has Data H:\
71 Has Data \\?\Volume{6537fec1-01bc-11d6-adb5-806e6f6e6963}\
72 Has Data D:\
81 Has Data \\?\Volume{6537fec2-01bc-11d6-adb5-806e6f6e6963}\
82 Has Data E:\

61 y 62 son duplicados de 11 y 12. Como mera coincidencia, esto sería curioso ya que los valores de %G en este punto exacto también son 11 y 12. Esto me lleva a sacar la conclusión de que... simplemente no Míralo.

Es !%%G! ¿De alguna manera me malinterpretaron o cometí un error con los conteos? ¡Me he golpeado la cabeza contra la pantalla durante tanto tiempo que realmente agradecería cualquier consejo!

EDITAR: Después de un descanso completo, me di cuenta de que después de que %%G pasa 10, es probable que ocurran conflictos como !%%G! se interpreta como !11! y !12!, que se refieren a variables de primer y segundo análisis. Esto da como resultado los duplicados. Sin embargo, el dilema persiste: ¿cómo evitarlo?

Establecer otra capa de localización resolvería el problema a costa de crear otras; No parece ser una opción viable. Podría usar letras en lugar de números como variables, pero esto rompería la aritmética. *Actualmente estamos investigando el uso de shift para reemplazar set /a count+=1 con un equivalente para letras, pero hasta ahora fue en vano.

Respuesta1

Puedes arreglar tu código simplemente poniendo un delimitador entre los dos números en los nombres de tus variables finales. Yo usaré un punto:

SET !A!.!B!=!%%G!
ECHO !A!.!B! Has Data !%%G!

O podrías poner un prefijo antes de cada nombre. Esta es una buena idea porque no se puede expandir un nombre de variable que comience con un dígito con expansión normal porque se confundirá con un argumento por lotes como %1. No hay problema con su código ya que usa expansión retrasada. Pero las variables que comienzan con un dígito son algo que generalmente se debe evitar.

SET V!A!!B!=!%%G!
ECHO V!A!!B! Has Data !%%G!

Probablemente haría ambas cosas. Me gusta la variable que comienza con algo que no sea un dígito y visualmente me gusta la separación de los dos números:

SET V!A!.!B!=!%%G!
ECHO V!A!.!B! Has Data !%%G!

Su código podría simplificarse drásticamente:

@echo off
setlocal enableDelayedExpansion
set /a count=0
for /f %%A in ('mountvol ^| findstr /l "\ *"') do (
  set /a "A=count/2+1, B=count%%2+1, count+=1"
  set "V!A!.!B!=%%A"
  echo V!A!.!B!=%%A
)

Que debería producir:

V1.1 Has Data \\?\Volume{d35e9775-0176-11d6-a06d-806e6f6e6963}\
V1.2 Has Data H:\
V2.1 Has Data \\?\Volume{d35e9776-0176-11d6-a06d-806e6f6e6963}\
V2.2 Has Data F:\
V3.1 Has Data \\?\Volume{6537febd-01bc-11d6-adb5-806e6f6e6963}\
V3.2 Has Data ***
V4.1 Has Data \\?\Volume{3fb54500-a257-11e4-8d8d-806e6f6e6963}\
V4.2 Has Data ***
V5.1 Has Data \\?\Volume{6537febe-01bc-11d6-adb5-806e6f6e6963}\
V5.2 Has Data C:\
V6.1 Has Data \\?\Volume{6537fec3-01bc-11d6-adb5-806e6f6e6963}\
V6.2 Has Data A:\
V7.1 Has Data \\?\Volume{6537fec1-01bc-11d6-adb5-806e6f6e6963}\
V7.2 Has Data D:\
V8.1 Has Data \\?\Volume{6537fec2-01bc-11d6-adb5-806e6f6e6963}\
V8.2 Has Data E:\

Al simplificar el código para usar solo un bucle, sin variables intermedias, técnicamente no hay necesidad de un prefijo o delimitador en el nombre de la variable. Simplemente podrías usar lo siguiente en mi bucle:

  set "!A!!B!=%%A"
  echo !A!!B! Has Data %%A

Pero aún así mantendría el prefijo y el delimitador.

Puede haber 10 o más volúmenes en una máquina; la mía tiene 10. Como sugiere Scott, puede agregar 100 al valor para obtener un nombre de variable de ancho fijo que admita hasta 99 volúmenes. También usaría una operación de subcadena para obtener valores con prefijo cero, comenzando con 01.

@echo off
setlocal enableDelayedExpansion
set /a count=0
for /f %%A in ('mountvol ^| findstr /l "\ *"') do (
  set /a "A=count/2+101, B=count%%2+1, count+=1"
  set "V!A:~-2!.!B!=%%A"
  echo V!A:~-2!.!B!=%%A
)

Respuesta2

Simplemente elimine los duplicados (elimine los conflictos) de los nombres de las variables medianteprefijandoellos con letras. Por ejemplo, en la primera pasada, utilice A1, A2, A3, ..., y/o utilice B11, B12, B21, B22, ..., en la segunda pasada.

En situaciones como esta, a veces encuentro que el nombre de la variable no es uniformelongitudes causa alguna dificultad. (Por ejemplo, A1... A9son dos caracteres, pero luego A10, etc., son tres caracteres). A veces lo manejo comenzando la numeración en 10 u 11, o 100 o 101. Por ejemplo, si comienzas con A10, puedes Tiene 90 líneas de entrada y solo llega hasta A99.

información relacionada