Descubrimiento en comando for

Iniciado por _carlos_, 23 Diciembre 2008, 03:02 AM

0 Miembros y 1 Visitante están viendo este tema.

_carlos_

El comando for /f nos permite leer un archivo o frase o la salida de un comando, por defecto leemos la primera palabra entre espacios y tabulación del contenido de un archivo de nombre corto, si queremos especificar una frase debemos encerrarla entre comillas, si indicamos la salida de un comando debemos hacerlo entre comillas simples. Si necesitamos indicar el nombre de un archivo de nombre largo, por ejemplo, uno que contenga espacios, si lo encerraramos entre comillas, en vez de indicar el nombre de un archivo para que lo lea, indicariamos el nombre del archivo como una frase, por ello, en este caso utilizaremos la opción usebackq que indice que las comillas inversas (`) es para los comandos, las comillas simples (') para las frases, y doble comillas para los nombres de archivos ("), sean de formato largo o corto.


Parte de su ayuda nos dice:

Ejecuta el comando para cada uno de los archivos especificados en el
conjunto de archivos.

FOR %variable IN (conjunto) DO comando [parámetros]

 %variable  Especifica un parámetro reemplazable de una sola letra.
 (conjunto)  Especifica un conjunto de uno o más archivos.  Se pueden
             usar comodines.
 comando     Especifica el comando que se ejecutará para cada archivo.
 parámetros  Especifica los parámetros o modificadores del comando
             especificado.

Para usar el comando FOR en un programa por lotes, especificar
%%variable en vez de %variable.  Los nombres de las variables
distinguen entre mayúsculas y minúsculas, por lo tanto %i no es lo
mismo que %I.


FOR /F ["opciones"] %variable IN (conjunto-archivo) comando DO [parámetros]
FOR /F ["opciones"] %variable IN ('cadena') comando
DO  [comando-parámetros]
FOR /F ["opciones"] %variable IN ('comando')comando
DO  [comando-parámetros]
o, si la opción usebackq está presente:
FOR /F ["opciones"] %variable IN (conjunto-archivo) comando DO [parámetros]
comando DO [comando-parámetros]
FOR /F ["opciones"] %variable IN ('cadena') comando
DO [parámetros]
FOR /F ["opciones"] %variable IN (`comando`) comando
DO [parámetros]
   Conjunto de archivos es uno o más nombres de archivos.
Cada archivo es abierto, leído y procesado antes de ir al siguiente archivo en el conjunto
de archivos.
Procesar consiste en leer el archivo, partirlo en líneas individuales de texto
y analizar cada línea en cero o más símbolos.  El cuerpo del bucle se llama
con los valores de la variable establecidos para las cadenas de símbolo
encontradas. De forma predeterminada, /F pasa el primer símbolo separado en
blanco desde cada línea .
Las líneas en blanco son saltadas.
Puede sustituir el comportamiento de análisis predeterminado si especifica el parámetro opcional "opciones".
Esto es una cadena entre comillas que contiene una o más palabras claves para especificar diferentes opciones
de análisis.
Las palabras claves son:
 


       eol=c           - especifica un carácter de comentario
                         al final de la línea (sólo uno)
       skip=n          - especifica el número de
                         líneas que hay que saltarse al principio
                         del archivo.
       delims=xxx      - especifica un grupo de delimitadores.
                         Esto reemplaza al grupo de delimitadores
                         predeterminados de espacio y tabulación.
       tokens=x,y,m-n  - especifica qu, símbolos de cada línea deben
                         pasarse al cuerpo de la cláusula "for" en
                         cada iteración.
                         Esto causará que los nombres de variables
                         adicionales sean asignados.
                         La forma m-n es un intervalo del símbolo
                         m-,simo al símbolo n-,simo. Si el último
                         carácter en la cadena tokens= es un asterisco,
                         se asigna una variable adicional que recibe el
                         resto del texto en la línea posterior al último
                         símbolo analizado.
       usebackq        - especifica que la nueva semántica está vigente,
                         donde una cadena entre comillas inversas se ejecuta
                         como un comando y una cadena con comillas simples
                         es un comando de cadena literal y permite el uso de
                         comillas dobles para entrecomillar los nombres de
                         archivo en un grupo de nombres de archivos.

Estos ejemplos pueden ayudar:

FOR /F "eol=; tokens=2,3* delims=, " %i in (archivo.txt) do     @echo %i %j %k

 analizará cada línea en mi archivo.txt excepto las que inicien con un punto
y coma, pasando el segundo y tercer símbolo de cada línea al cuerpo de FOR.  
Los símbolos están delimitados por comas y/o espacios.
Tenga en cuenta que las instrucciones del cuerpo de FOR hacen referencia a %i para obtener el segundo símbolo,
a %j para obtener el tercero y a %k para obtener el resto de los símbolos posteriores al tercero.
Para los nombres de archivo que contengan espacios, necesita poner poner comillas dobles en los nombres de archivos.
Para usar comillas dobles de esta manera, tambi,n necesita usar la opción usebackq, de lo contrario las comillas dobles
serán interpretadas para definir el análisis de una cadena literal.
%i está explícitamente declarado en la instrucción y %i está explícitamente declarado en la instrucción FOR,
%j y %k están declarados implícitamente a trav,s de la opción =tokens. Puede especificar
hasta 26 símbolos a trav,s de la línea =tokens, siempre y cuando no cause
un intento de declarar una variable mayor que la letra 'z' o 'Z'.
Recuerde, los nombres de variables de FOR son de una sola letra y distinguen mayúsculas de minúscula.
Además, las variables son globales y no puede haber más de 52 variables activas al mismo tiempo.  
 Tambien puede usar la lógica de análisis de FOR /F en una cadena inmediata convirtiendo el conjunto de
archivos entre par,ntesis en una cadena entre
comillas usando caracteres con comillas simples. Será tratada y analizada
como una simple línea de entrada de un archivo.
Finalmente, puede usar el comando FOR /F para analizar la salida de un comando.
Se hace convirtiendo el conjunto de archivos entre par,ntesis una cadena con comillas invertidas.
Se tratará como una línea de comandos que se pasa a un CMD.EXE secundario y la salida es capturada en
memoria y evaluada como si fuera un archivo.  Como en el siguiente ejemplo:

     FOR /F "usebackq delims==" %i IN (`conjunto`) DO     @echo %i

enumerará los nombres de variable de entorno en el entorno actual.

 


La documentación del comando for /f dice lo siguiente:



Puede especificar hasta 26 símbolos a través de la línea =tokens,
siempre y cuando no cause un intento de declarar una variable mayor que la letra 'z' o 'Z'.

Recuerde, los nombres de variables de FOR son de una sola letra
y distinguen mayúsculas de minúscula. Además, las variables son globales y
no puede haber más de 52 variables activas al mismo tiempo.


Haciendo pruebas de qué significa especificar hasta 26 símbolos a través de la línea =tokens
pensé que significaba escribir más 26 carácteres dentro del tokens, pero no se refiere a eso, pues esto funciona:


@echo off

set palabras=p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 p16 p17 p18 p19 p20 p21 p22 p23 p24 p25 p26 p27 p28 p29 p30

for /f "tokens=1-30" %%a in ("%palabras%") do (
echo %%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z
)

for /f tokens=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30" %%a in ("%palabras%") do (
echo %%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z
)

pause



Si nos fijamos en el segundo caso utilizamos más de 26 símbolos en tokens= por lo que a lo que se refiere es que no podemos usar más de 26 variables dentro del for.


Recuerde, los nombres de variables de FOR son de una sola letra y distinguen mayúsculas de minúscula.


Eso indica que los nombres de las variables son letras mayúsculas o minúsculas, por lo tanto no es lo mismo %%a que %%A

Bueno, ¿a qué se refiere con los carácteres mayores que z o Z? Justamente a eso. Sin embargo yo demostraré algo no documentado descubierto por mi, o al menos, lo aprendí yo solo, y no lo leí en ninguna parte.


Es posible usar más de 26 variables, concretamente 31, y carácteres mayores que z o Z, aunque el comando if diga lo contrario.

La generación implícita de variables de la que habla la ayuda del comando for la encontré estudiando la tabla ascii de códigos activa. Para más información vean el manual de chcp.exe http://technet.microsoft.com/en-us/library/bb490874.aspx

Los que usamos el cmd.exe en español usamos la tabla 850. Podemos ver dicha tabla en http://www.ascii.ca/cp850.htm

En dicha tabla se muestran algunos carácteres antes de la A y después de la Z, y antes de la a y después de la z.

Bien, ¿podremos usar dichos carácteres en el comando interno for? No, y hasta aquí llego el descubrimiento ... xD broma, sí se puede. Algunos son delimitadores propios del cmd.exe, como por ejemplo: el ; y el = por lo que no podremos utilizarlos.

Por lo que además de usar los típicos %%a - %%z y %%A - %%Z y máximo "tokens=26" podremos usar %%otroCarácter y máximo "tokens=31"

Nota: si en el comando for escribimos en "tokens=1-32" cmd.exe no ejecutará el cuerpo del comando for.


Para for /f "token=1" o simplemente for /f podremos usar los siguientes carácteres:

&
:
<


y para for /f de más de un token, podremos comenzar desde y llegar a carácteres dentro de este rango de menor a mayor:



>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}


Nota: los siguientes carácteres: debemos anteponerles un ^


^
<
>
|
&


por lo que quedarán así:


^^
^<
^>
^|
^&



Finalmente les dejo unos ejemplos:


@echo off

set palabras=p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 p16 p17 p18 p19 p20 p21 p22 p23 p24 p25 p26 p27 p28 p29 p30 p31 p32 p33 p34 p35

for /f "tokens=1" %%^& in ("%palabras%") do (
echo %%^&
)

for /f "tokens=1" %%^< in ("%palabras%") do (
echo %%^<
)

for /f "tokens=1,2,3" %%^> in ("%palabras%") do (
echo %%^>%%?%%@
)


for /f "tokens=1-31" %%? in ("%palabras%") do (
echo %%?%%@%%A%%B%%C%%D%%E%%F%%G%%H%%I%%J%%K%%L%%M%%N%%O%%P%%Q%%R%%S%%T%%U%%V%%W%%X%%Y%%Z%%[%%\%%]
)

for /f "tokens=1-31" %%^^ in ("%palabras%") do (
echo %%^^%%_%%`%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z%%{%%^|
)

for /f "tokens=1-31" %%_ in ("%palabras%") do (
echo %%_%%`%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z%%{%%^|%%}
)

pause



[actualizado]
La utilidad de mi descubrimiento es que por ejemplo si antes declaraban:


for /f "tokens=1-4" %%Y in ("p1 p2 p3 p4") do (
echo %%Y%%Z...
)


y querían mostrar el token 1,2,3,4 solo podíamos mostrar el token 1 y 2, porque luego de %%Y viene %%Z y después ... no sabíamos que letra venía.

Entonces ahora podemos hacer:

for /f "tokens=1-4" %%Y in ("p1 p2 p3 p4") do (
echo %%Y%%Z%%[%%\
)


Lo otro, la documentación decía 52 variables, es decir 26 + 26 (a-z) y (A-Z) un for dentro de otro for, o varios for, utilizando de manera única una letra del abecedario mayúscula o minúscula, sin embargo ahora tenemos más de 65 variables, por ejemplo:


@echo off

for /f "tokens=1-10" %%^> in ("El cmd.exe es el interprete de comandos en OS2 y") do (
for /f "tokens=1-10" %%H in ("sistemas basados en Windows NT incluyendo Windows 2000 Windows XP") do (
for /f "tokens=1-8" %%R in ("Windows Server 2003 y Windows Vista. Es el") do (
for /f "tokens=1-12" %%Z in ("equivalente de command.com en MS-DOS y sistemas de la familia Windows 9x.") do (
for /f "tokens=1-10" %%f in ("A diferencia de su antecesor command.com este programa es tan") do (
for /f "tokens=1-14" %%p in ("solo una aplicacion no es una parte del sistema operativo y no posee la") do (
echo %%^>%%?%% @%%A%%B%%C%%D%%E%%F%%G%%H%%I%%J%%K%%L%%M%%N%%O%%P%%Q%%R%%S%%T%%U%%V%%W%%X%%Y%%Z%%[%%\%%]%%^^%%_%%`%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z%%{%%^|%%}
)
)
)
)
)
)

pause


toda gracias a la excelente documentación de Microsoft.

Entonces, en resumen, mi descubrimiento aumenta el máximo de tokens de 26 a 31, y el máximo de variables globales del for, de 52 a más de 65, digo más porque en el ejemplo solo utilizé las que están dentro del rango, pero no utilizé carácteres individuales.




Escrito por Carlos.

leogtz

Jeje, excelente Carlos, lo lei completo.

Tambien este funciona :
FOR /F "TOKENS=3" %%.  IN ('VER') DO (ECHO:%%.)


Saludos.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

_carlos_

De nada RockoX, sabes lo descubrí intentando mostrar los números del 1 a 255 sin el típico for /l, de esta forma:


setlocal enabledelayedexpansion
set /a numero=1
for /l %%%% in (-1) do (
if !numero! gtr 255 (goto:eof)
echo.!numero!
set /a numero +=1
)
endlocal


Se me ocurrió probar el % (lo  coloqué doble porque así lo exige cmd) y funcionó, entonces investigué el rango de otros carácteres que es lo importante y así poder aumentar el rango de palabras de 26 (documentado) a 31 (no documentado).

Si te fijas, también se puede con el %, pero no lo coloqué en el artículo porque no sirve para mostrar el contenido de dicha variable con un echo o usarla dentro del cuerpo del for.



leogtz

#3
Con el
.
No serian 32 ?

Edito:

Tambien esto me funciona, con el caracter "°" :
FOR /F "TOKENS=3" %%° IN ('VER') DO (
ECHO.%%°
)

Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

_carlos_

#4
Cita de: Leo Gutierrez. en 23 Diciembre 2008, 04:58 AM
Con el
.
No serian 32 ?

Edito:

Tambien esto me funciona, con el caracter "°" :
FOR /F "TOKENS=3" %%° IN ('VER') DO (
ECHO.%%°
)



Son 31 variables con 31 cadenas de texto cada una, por eso, el 31 no es a la cantidad de carácteres que puedas usar después del %% pues como tú dices pueden usarse más, pero te permiten usar solo un token, sino en la cantidad máxima de palabras que puedes usar utilizando variables, que deben tener una sucesión numérica para cmd.
Por ejemplo, si quieres extraer los dos primeros tokens o palabras de "hola mundo" y usas la variable %%a para referenciar al primer token, deberás usar %%b para referenciar a la segunda.

Usando tu ejemplo:
como lo adaptarías para extraer la cuarta palabra también:

FOR /F "TOKENS=3,4" %%° IN ('VER') DO (
ECHO.%%°
)


_carlos_

#5
La utilidad de mi descubrimiento es que por ejemplo si antes declaraban:


for /f "tokens=1-4" %%Y in ("p1 p2 p3 p4") do (
echo %%Y%%Z...
)


y querían mostrar el token 1,2,3,4 solo podíamos mostrar el token 1 y 2, porque luego de %%Y viene %%Z y después ... no sabíamos que letra venía.

Entonces ahora podemos hacer:

for /f "tokens=1-4" %%Y in ("p1 p2 p3 p4") do (
echo %%Y%%Z%%[%%\
)


Lo otro, la documentación decía 52 variables, es decir 26 + 26 (a-z) y (A-Z) un for dentro de otro for, o varios for, utilizando de manera única una letra del abecedario mayúscula o minúscula, sin embargo ahora tenemos más de 65 variables, por ejemplo:


@echo off

for /f "tokens=1-10" %%^> in ("El cmd.exe es el interprete de comandos en OS2 y") do (
for /f "tokens=1-10" %%H in ("sistemas basados en Windows NT incluyendo Windows 2000 Windows XP") do (
for /f "tokens=1-8" %%R in ("Windows Server 2003 y Windows Vista. Es el") do (
for /f "tokens=1-12" %%Z in ("equivalente de command.com en MS-DOS y sistemas de la familia Windows 9x.") do (
for /f "tokens=1-10" %%f in ("A diferencia de su antecesor command.com este programa es tan") do (
for /f "tokens=1-14" %%p in ("solo una aplicacion no es una parte del sistema operativo y no posee la") do (
echo %%^>%%?%%@%%A%%B%%C%%D%%E%%F%%G%%H%%I%%J%%K%%L%%M%%N%%O%%P%%Q%%R%%S%%T%%U%%V%%W%%X%%Y%%Z%%[%%\%%]%%^^%%_%%`%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j%%k%%l%%m%%n%%o%%p%%q%%r%%s%%t%%u%%v%%w%%x%%y%%z%%{%%^|%%}
)
)
)
)
)
)

pause


toda gracias a la excelente documentación de Microsoft.

Entonces, en resumen, mi descubrimiento aumenta el máximo de tokens de 26 a 31, y el máximo de variables globales del for, de 52 a más de 65, digo más porque en el ejemplo solo utilizé las que están dentro del rango, pero no utilizé carácteres individuales, como el punto, como mostró Leo.



_carlos_

#6
Acabo de buscar la documentación del comando for, pero esta vez en el archivo llamado ntcmds.chm de windows xp service pack 3

y dice lo siguiente, lo único diferente es que dice que se pueden usar cualquier carácter:

///////////////////

Notas
Utilizar el comando for
Puede utilizar el comando for en un archivo por lotes o directamente desde el símbolo del sistema.

Utilizar parámetros de proceso por lotes
Los siguientes atributos se aplican al comando for:

El comando for reemplazará %variable o %%variable por cada cadena de texto en el grupo especificado, hasta que el comando haya procesado todos los archivos.
Los nombres de variable en for distinguen entre mayúsculas y minúsculas, son globales y no puede haber más de 52 activos en total al mismo tiempo.
Para evitar confusión con los parámetros por lotes de %0 a %9, puede utilizar cualquier carácter como variable excepto los números del 0 al 9. Para archivos por lotes sencillos, un único carácter como %%f puede ser suficiente.
Puede utilizar múltiples valores para variable en archivos por lotes complejos con el fin de distinguir entre las distintas variables reemplazables.

%i se declara explícitamente en la instrucción FOR; %j y %k se declaran implícitamente mediante tokens=. Puede especificar hasta 26 testigos mediante tokens=, siempre que no intente declarar una variable superior a la letra 'z' o 'Z'.

///////////////////

Aunque de todas formas, ya he demostrado que se pueden usar 31 tokens o testigos en vez de 26, y usar más de 65 nombres de variables activos al mismo tiempo, en vez de 52, y publiqué el rango que utiliza cmd, que tampoco se dice en la documentación.
Así es que me quedo tranquilo de que realmente he publicado algo no documentado.

Nota: revisaré el archivo ntcmds.chm de windows vista para saber si dice algo de lo que yo he publicado.
[editado]
Revisé en Windows Vista y no hallé un archivo de ayuda para cmd, y la documentación del cmd.exe del comando for no dice más que lo que dice la que aparece en el cmd.exe de Windows XP.


Meta

Buen trabajo Carlitos, quizás descubras más cosas por ahí.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

leogtz

#8
Cita de: _carlos_ en 23 Diciembre 2008, 08:31 AM
La utilidad de mi descubrimiento es que por ejemplo si antes declaraban:


for /f "tokens=1-4" %%Y in ("p1 p2 p3 p4") do (
echo %%Y%%Z...
)


y querían mostrar el token 1,2,3,4 solo podíamos mostrar el token 1 y 2, porque luego de %%Y viene %%Z y después ... no sabíamos que letra venía.

Entonces ahora podemos hacer:

for /f "tokens=1-4" %%Y in ("p1 p2 p3 p4") do (
echo %%Y%%Z%%[%%\
)



Carlos, me acabo de encontrar un codigo en la web de Rob Van Der Woude que ya utilizaba caracteres fuera de a-z A-Z, hechale un vistazo:

http://www.robvanderwoude.com/amb_shortcutsnt.html


Citarfor /f "tokens=*" %%? in (
'dir/b/a %1? 2^>nul') do (set name=%%~nx?)
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

_carlos_

Si, otras personas se dieron cuenta de que podían usarse otros carácteres en el comando for. Al parecer no he sido el primero en haberme dado cuenta, aunque si me considero uno de los primeros en documentarlo de forma explícita, pues busqué y no hallé ningún artículo como el que yo escribí, con el rango y los ejemplos. En http://groups.google.com/group/alt.msdos.batch.nt/ me dijeron que lo que yo expliqué había sido usado innumberables veces, que la ignorancia no era parte de su grupo, un poco pedante el comentario, pero de todas formas, no me dieron ninguna prueba de algún código que mostrará o fundamentara su afirmación, tal vez existan códigos que usen otros carácteres en el comando for, pero que usen varios carácteres distintos de letras usando varios tokens, no lo he visto.