Войти

Показать полную графическую версию : [решено] Реализация функций длины переменной, выделение подстроки с параметрами в переменной.


NiOl
08-07-2009, 17:26
Частенько приходится городить огород для получения достаточно простого результата.

1. Есть переменная, допустим set a=qwertyuiop Вопрос, как узнать ее длину? Сейчас мне приходится писать доп. функцию из 8 строк.

2. Есть переменная, нужно выделить из нее часть, но позиция/длина хранятся в других переменных и простое set b=%a:~%b%,%c% % и различные вариации не прокатят.

3. Некоторое время назад... (хорошо сказал :teeth: ) в батнике мжно было проворачивать "макросы", т.е. присвоить переменной целую команду, затем в нужном месте вместо комады в строке стояла просто переменная, которая исполнялась по своему содержимому. С помощью такого "самомодифицирующегося кода" удавалось обойти некоторые ограничения.

amel27
08-07-2009, 18:48
1. Увы, без процедур пока не выходит: :(
@Echo Off

Call :StringLen "qwert yuiop"
Echo %$StringLen%

:StringLen
:: -----------------------
:: Нахождение длины строки
:: -----------------------
:: %1 - текстовая строка
:: -----------------------
Set $StringLen=0&Set $StringBuf=%~1
If ""=="%~1" GoTo :EOF
:StringLenLoop
Set /A $StringLen+=1
Call Set $StringChr=%%$StringBuf:~%$StringLen%%%
If ""=="%$StringChr%" GOTO :EOF
GoTo :StringLenLoop

2. Два варианта:
@Echo Off

Set a=qwertyuiop
Set b=1
Set c=2

Call Set d=%%a:~%b%,%c%%%
Echo %d%

@Echo Off
SetLocal EnableDelayedExpansion

Set a=qwertyuiop
Set b=1
Set c=2

Set d=!a:~%b%,%c%!
Echo %d%
3. Вроде работает: :dont-know
@Echo Off

Set $CMD=DIR
Call %$CMD%

NiOl
08-07-2009, 19:30
Забавно, в CALL /? нигде не упоминается такой забавный способ, как вызов ДОС-команды.
т.е. я просто использовал %$CMD% вместо Call %$CMD%.

2й вариант 2го пункта я в свое время пробовал с точностью наоборот, т.е. Set d=%a:~!b!,!c!%, и даже для правильности оборачивал его в проверку условия: if 0==0 Set d=%a:~!b!,!c!% и никакого результата на выходе. Не понимаю.

Для 1го пункта пользуюсь такой заготовкой (по идее Ваш код должен выполняться быстрее, т.к. у меня более длинная операция над строкой, но писалось с учетом известных мне тогда возможностей):
@echo off
SetLocal EnableExtensions
SetLocal EnableDelayedExpansion

call :Lenght qwertyuiop
echo %Len%
exit

:Lenght
set Len=0
set LenghtStr=%1
:Lenght1
if "%LenghtStr%"=="" exit /b
set LenghtStr=%LenghtStr:~0,-1%
set /a Len+=1
goto Lenght1

amel27
09-07-2009, 09:15
вспомнил ещё один способ определения длины в две строки:
@Echo Off
Set a=qwertyuiop

Echo.%a%>"%TEMP%\%~n0.tmp"
For %%i In ("%TEMP%\%~n0.tmp") Do Set /A z=%%~zi-2

Echo %z%

na_PaLm
06-07-2010, 23:18
@ECHO OFF
REM Var
SET var=1234567890абвгдежзийabcdefghij#_

CALL :_Timer
SET nn=0
:Loop
SET /a nn+=1
REM ------------------------------ 2х строчный вариант ------------------------------
<NUL SET /p "ECHO=%var%" > "qwe.txt"
FOR /F %%f IN ("qwe.txt") DO ( SET /a "zoo=%%~zf" )
REM DEL "qwe.txt" /f /q
REM ---------------------------------------------------------------------------------
IF "%nn%"=="1000" ( GOTO :EndLoop )
GOTO :Loop

:EndLoop
SET /a otimer=%timer%
CALL :_Timer
SET /a res=%timer% -%otimer%
ECHO %res% ms

PAUSE >NUL
EXIT

:_Timer
FOR /F "usebackq tokens=*" %%f IN (`^<NUL TIME ^| FIND /i "’ҐЄг饥 ўаҐ¬п:"`) DO ( SET "timer=%%f" )
SET timer=%timer:~-11%
SET /a timer=%timer:~0,2% *3600000 +%timer:~3,2% *60000 +%timer:~6,2% *1000 +%timer:~-2% *10
GOTO :EOF
Время выполнения: 4980 ms
С раскоментированной строкой «DEL "qwe.txt" /f /q»: 5840 ms

@ECHO OFF
REM Var
SET var=1234567890абвгдежзийabcdefghij#_

CALL :_Timer
SET nn=0
:Loop
SET /a nn+=1
REM ------------------------------ 6ти строчный вариант -----------------------------
SET $StringLen=0
:StrLoop
SET /a $StringLen+=1
CALL SET $StringChr=%%var:~%$StringLen%%%
IF "%$StringChr%"=="" ( GOTO :EndStrLoop )
GOTO :StrLoop
:EndStrLoop
REM ---------------------------------------------------------------------------------
IF "%nn%"=="1000" ( GOTO :EndLoop )
GOTO :Loop

:EndLoop
SET /a otimer=%timer%
CALL :_Timer
SET /a res=%timer% -%otimer%
ECHO %res% ms

PAUSE >NUL
EXIT

:_Timer
FOR /F "usebackq tokens=*" %%f IN (`^<NUL TIME ^| FIND /i "’ҐЄг饥 ўаҐ¬п:"`) DO ( SET "timer=%%f" )
SET timer=%timer:~-11%
SET /a timer=%timer:~0,2% *3600000 +%timer:~3,2% *60000 +%timer:~6,2% *1000 +%timer:~-2% *10
GOTO :EOF
Время выполнения: 112270 ms (~ в 20 раз дольше при 32х символьной строке)

awkozlov
05-06-2013, 05:17
По моему самое удачное от XGuest http://forum.script-coding.com/viewtopic.php?id=7949

@echo off
call :len var "строка" &:: "var" - Переменная куда вернуть значение
echo Длина строки: %var%
goto :eof

:len
set len=%~2
if not "%len%"=="" set /a %1+=1 & call :len %1 "%len:~1%"
goto :eof

CyberMuesli
08-06-2013, 00:26
делюсь бриллиантом

::===========================================================================
:StrLen
::===========================================================================
:: %1=VarName (not VALUE), ret !strLen!
set StrLen.S=A!%~1!
set StrLen=0
for /L %%P in (12,-1,0) do (
set /a "StrLen|=1<<%%P"
for %%I in (!StrLen!) do if "!StrLen.S:~%%I,1!"=="" set /a "StrLen&=~1<<%%P"
)
goto :eof

fhrbc
31-01-2019, 19:58
1.:LEN :: Длина строки
set "STRING=%STRING:~0,-1%" && set /a "LEN+=1"
if defined STRING goto LEN
Переменная STRING стирается, т.е. является временной




© OSzone.net 2001-2012