Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Реализация функций длины переменной, выделение подстроки с параметрами в переменной. (http://forum.oszone.net/showthread.php?t=144548)

NiOl 08-07-2009 17:26 1162219

Реализация функций длины переменной, выделение подстроки с параметрами в переменной.
 
Частенько приходится городить огород для получения достаточно простого результата.

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

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

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

amel27 08-07-2009 18:48 1162296

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 1162333

Забавно, в 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 1162720

вспомнил ещё один способ определения длины в две строки:
Код:

@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 1448664

Код:

@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 2162478

По моему самое удачное от 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 2164186

делюсь бриллиантом

Код:

::===========================================================================
: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 2855626

1.
Код:

:LEN :: Длина строки
set "STRING=%STRING:~0,-1%" && set /a "LEN+=1"
if defined STRING goto LEN

Переменная STRING стирается, т.е. является временной


Время: 15:13.

Время: 15:13.
© OSzone.net 2001-