vol ver pantalla mostrar mensaje ejemplos comandos comando bat archivos windows string batch-file

windows - pantalla - ver comandos



¿Cómo se obtiene la longitud de la cadena en un archivo por lotes? (12)

No parece haber una manera fácil de obtener la longitud de una cadena en un archivo por lotes. P.ej,

SET MY_STRING=abcdefg SET /A MY_STRING_LEN=???

¿Cómo encontraría la longitud de cadena de MY_STRING ?

Puntos de bonificación si la función de longitud de cadena maneja todos los caracteres posibles en cadenas, incluidos los caracteres de escape, así: !%^^()^! .


Acabo de encontrar la solución ULTIMATE:

set "MYSTRING=abcdef!%%^^()^!" (echo "%MYSTRING%" & echo.) | findstr /O . | more +1 | (set /P RESULT= & call exit /B %%RESULT%%) set /A STRLENGTH=%ERRORLEVEL%-5 echo string "%MYSTRING%" length = %STRLENGTH%

El resultado es:

string "abcdef!%^^()^!" length = 14

Maneja los caracteres de escape, un orden de magnitud más simple que la mayoría de las soluciones anteriores, y no contiene bucles, números mágicos, DelayedExpansion, archivos temporales, etc.

En caso de que el uso fuera del script por lotes (es decir, poner comandos en la consola manualmente), reemplace %%RESULT%% clave con %RESULT% .

Si es necesario, la variable %ERRORLEVEL% se puede establecer en FALSE utilizando cualquier comando NOP, por ejemplo, echo. >nul echo. >nul


Como no hay una función incorporada para la longitud de la cadena, puede escribir su propia función así:

@echo off setlocal set "myString=abcdef!%%^^()^!" call :strlen result myString echo %result% goto :eof :strlen <resultVar> <stringVar> ( setlocal EnableDelayedExpansion set "s=!%~2!#" set "len=0" for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do ( if "!s:~%%P,1!" NEQ "" ( set /a "len+=%%P" set "s=!s:~%%P!" ) ) ) ( endlocal set "%~1=%len%" exit /b )

Esta función necesita siempre 13 bucles, en lugar de una función strlen simple que necesita strlen-loops.
Maneja todos los personajes.


Las primeras líneas son simplemente para demostrar la función: strLen.

@echo off set "strToMeasure=This is a string" call :strLen strToMeasure strlen echo.String is %strlen% characters long exit /b :strLen setlocal enabledelayedexpansion :strLen_Loop if not "!%1:~%len%!"=="" set /A len+=1 & goto :strLen_Loop (endlocal & set %2=%len%) goto :eof

Por supuesto, esto no es tan eficiente en la versión "13 loop" proporcionada por jeb. Pero es más fácil de entender, y su computadora 3GHz puede pasar por algunas miles de iteraciones en una pequeña fracción de segundo.


Me gusta el enfoque de dos líneas de jmh_gr.

No funcionará con números de un solo dígito a menos que ponga () alrededor de la parte del comando antes de la redirección. ya que 1> es un comando especial "Echo is On" se redireccionará al archivo.

Este ejemplo debería ocuparse de los números de un solo dígito, pero no de los otros caracteres especiales, como < que pueden estar en la cadena.

(ECHO %strvar%)> tempfile.txt


Prefiero la respuesta aceptada de jeb : es la solución más rápida conocida y la que uso en mis propios scripts. (De hecho, hay algunas optimizaciones adicionales en DosTips, pero no creo que valen la pena)

Pero es divertido crear nuevos algoritmos eficientes. Aquí hay un nuevo algoritmo que usa la opción FINDSTR / O:

@echo off setlocal set "test=Hello world!" :: Echo the length of TEST call :strLen test :: Store the length of TEST in LEN call :strLen test len echo len=%len% exit /b :strLen strVar [rtnVar] setlocal disableDelayedExpansion set len=0 if defined %~1 for /f "delims=:" %%N in ( ''"(cmd /v:on /c echo(!%~1!&echo()|findstr /o ^^"'' ) do set /a "len=%%N-3" endlocal & if "%~2" neq "" (set %~2=%len%) else echo %len% exit /b

El código resta 3 porque el analizador hace malabares con el comando y agrega un espacio antes de que CMD / V / C lo ejecute. Se puede prevenir mediante el uso de (echo(!%~1!^^^) .

Para aquellos que quieren el rendimiento absoluto más rápido posible, la respuesta de jeb puede adoptarse para su uso como un lote "macro" con argumentos . Esta es una técnica avanzada de lotes desarrollada en DosTips que elimina el proceso inherentemente lento de CALLing a: subrutina. Puede obtener más información acerca de los conceptos detrás de las macros de proceso por lotes aquí , pero ese enlace utiliza una sintaxis más primitiva y menos deseable.

A continuación se muestra una macro @strLen optimizada, con ejemplos que muestran las diferencias entre el uso de macro y: subrutina, así como las diferencias en el rendimiento.

@echo off setlocal disableDelayedExpansion :: -------- Begin macro definitions ---------- set ^"LF=^ %= This creates a variable containing a single linefeed (0x0A) character =% ^" :: Define %/n% to effectively issue a newline with line continuation set ^"/n=^^^%LF%%LF%^%LF%%LF%^^" :: @strLen StrVar [RtnVar] :: :: Computes the length of string in variable StrVar :: and stores the result in variable RtnVar. :: If RtnVar is is not specified, then prints the length to stdout. :: set @strLen=for %%. in (1 2) do if %%.==2 (%/n% for /f "tokens=1,2 delims=, " %%1 in ("!argv!") do ( endlocal%/n% set "s=A!%%~1!"%/n% set "len=0"%/n% for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (%/n% if "!s:~%%P,1!" neq "" (%/n% set /a "len+=%%P"%/n% set "s=!s:~%%P!"%/n% )%/n% )%/n% for %%V in (!len!) do endlocal^&if "%%~2" neq "" (set "%%~2=%%V") else echo %%V%/n% )%/n% ) else setlocal enableDelayedExpansion^&setlocal^&set argv=, :: -------- End macro definitions ---------- :: Print out definition of macro set @strLen :: Demonstrate usage set "testString=this has a length of 23" echo( echo Testing %%@strLen%% testString %@strLen% testString echo( echo Testing call :strLen testString call :strLen testString echo( echo Testing %%@strLen%% testString rtn set "rtn=" %@strLen% testString rtn echo rtn=%rtn% echo( echo Testing call :strLen testString rtn set "rtn=" call :strLen testString rtn echo rtn=%rtn% echo( echo Measuring %%@strLen%% time: set "t0=%time%" for /l %%N in (1 1 1000) do %@strlen% testString testLength set "t1=%time%" call :printTime echo( echo Measuring CALL :strLen time: set "t0=%time%" for /l %%N in (1 1 1000) do call :strLen testString testLength set "t1=%time%" call :printTime exit /b :strlen StrVar [RtnVar] :: :: Computes the length of string in variable StrVar :: and stores the result in variable RtnVar. :: If RtnVar is is not specified, then prints the length to stdout. :: ( setlocal EnableDelayedExpansion set "s=A!%~1!" set "len=0" for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do ( if "!s:~%%P,1!" neq "" ( set /a "len+=%%P" set "s=!s:~%%P!" ) ) ) ( endlocal if "%~2" equ "" (echo %len%) else set "%~2=%len%" exit /b ) :printTime setlocal for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100 for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100 set /a tm=t1-t0 if %tm% lss 0 set /a tm+=24*60*60*100 echo %tm:~0,-2%.%tm:~-2% msec exit /b

- Muestra de salida -

@strLen=for %. in (1 2) do if %.==2 ( for /f "tokens=1,2 delims=, " %1 in ("!argv!") do ( endlocal set "s=A!%~1!" set "len=0" for %P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do ( if "!s:~%P,1!" neq "" ( set /a "len+=%P" set "s=!s:~%P!" ) ) for %V in (!len!) do endlocal&if "%~2" neq "" (set "%~2=%V") else echo %V ) ) else setlocal enableDelayedExpansion&setlocal&set argv=, Testing %@strLen% testString 23 Testing call :strLen testString 23 Testing %@strLen% testString rtn rtn=23 Testing call :strLen testString rtn rtn=23 Measuring %@strLen% time: 1.93 msec Measuring CALL :strLen time: 7.08 msec


Puede hacerlo en dos líneas, completamente en un archivo por lotes, escribiendo la cadena en un archivo y luego obteniendo la longitud del archivo. Solo tiene que restar dos bytes para tener en cuenta el CR + LF automático agregado al final.

Digamos que su cadena está en una variable llamada strvar :

ECHO %strvar%> tempfile.txt FOR %%? IN (tempfile.txt) DO ( SET /A strlength=%%~z? - 2 )

La longitud de la cadena está ahora en una variable llamada strlength .

En un poco más de detalle:

  • FOR %%? IN (filename) DO ( ... FOR %%? IN (filename) DO ( ... : obtiene información sobre un archivo
  • SET /A [variable]=[expression] : evalúa la expresión numéricamente
  • %%~z? : Expresión especial para obtener la longitud del archivo

Para mezclar todo el comando en una línea:

ECHO %strvar%>x&FOR %%? IN (x) DO SET /A strlength=%%~z? - 2&del x


Quiero adelantar esto diciendo que no sé mucho sobre cómo escribir código / script / etc. pero pensé que compartiría una solución que parece haber surgido. La mayoría de las respuestas aquí me pasaron por alto, así que tenía curiosidad por saber si lo que he escrito es comparable.

@echo off set stringLength=0 call:stringEater "It counts most characters" echo %stringLength% echo.&pause&goto:eof :stringEater set var=%~1 :subString set n=%var:~0,1% if "%n%"=="" ( goto:eof ) else if "%n%"==" " ( set /a stringLength=%stringLength%+1 ) else ( set /a stringLength=%stringLength%+1 ) set var=%var:~1,1000% if "%var%"=="" ( goto:eof ) else ( goto subString ) goto:eof


Sí, por supuesto que hay una manera fácil, usando vbscript (o powershell).

WScript.Echo Len( WScript.Arguments(0) )

guardar esto como strlen.vbs y en la línea de comandos

c:/test> cscript //nologo strlen.vbs "abcd"

Use un bucle for para capturar el resultado (o use vbscript por completo para su tarea de creación de scripts)

Ciertamente es mejor tener que crear soluciones engorrosas utilizando lotes y no hay excusa para no usarlo, ya que vbscript está disponible con cada distribución de Windows (y con powershell en adelante).


Si tienes Windows Vista +, prueba este método de Powershell:

For /F %%L in (''Powershell $Env:MY_STRING.Length'') do ( Set MY_STRING_LEN=%%L )

o alternativamente:

Powershell $Env:MY_STRING.Length > %Temp%/TmpFile.txt Set /p MY_STRING_LEN = < %Temp%/TmpFile.txt Del %Temp%/TmpFile.txt

Estoy en Windows 7 x64 y esto está funcionando para mí.


Solo otro script por lotes para calcular la longitud de una cadena, en solo unas pocas líneas. Puede que no sea el más rápido, pero es bastante pequeño. La subrutina ": len" devuelve la longitud en el segundo parámetro. El primer parámetro es la cadena real que se analiza. Tenga en cuenta que los caracteres especiales deben ser escapados, ese es el caso con cualquier cadena en el archivo por lotes.

@echo off setlocal call :len "Sample text" a echo The string has %a% characters. endlocal goto :eof :len <string> <length_variable> - note: string must be quoted because it may have spaces setlocal enabledelayedexpansion&set l=0&set str=%~1 :len_loop set x=!str:~%l%,1!&if not defined x (endlocal&set "%~2=%l%"&goto :eof) set /a l=%l%+1&goto :len_loop


@echo off :: warning doesn''t like * ( in mystring setlocal enabledelayedexpansion set mystring=this is my string to be counted forty one call :getsize %mystring% echo count=%count% of "%mystring%" set mystring=this is my string to be counted call :getsize %mystring% echo count=%count% of "%mystring%" set mystring=this is my string call :getsize %mystring% echo count=%count% of "%mystring%" echo. pause goto :eof :: Get length of mystring line ######### subroutine getsize ######## :getsize set count=0 for /l %%n in (0,1,2000) do ( set chars= set chars=!mystring:~%%n! if defined chars set /a count+=1 ) goto :eof :: ############## end of subroutine getsize ########################


@echo off & setlocal EnableDelayedExpansion set Var=finding the length of strings for /l %%A in (0,1,10000) do if not "%Var%"=="!Var:~0,%%A!" (set /a Length+=1) else (echo !Length! & pause & exit /b)

establece la var a lo que quieras para encontrar la longitud de la misma o cámbiala a set / p var = para que el usuario la ingrese. Poniendo esto aquí para referencia futura.