0

I'm declaring and defining 5 strings, which I then perform some analysis on via function calls. The first function calculates the length of the strings, and the second count the spaces in the strings. The last two functions are not implemented yet. When I run the batch script, I get several errors saying "Missing operand". I think the problem has to do with localization of variables. Can anyone figure out how to solve the problem? Does the line setlocal EnableExtensions EnableDelayedExpansion ... endlocal also make the variables in the block local besides enable extensions and delayed expansion?

@REM File:      String analysis.bat
@REM Author:    Jakob Kjeldberg Andersen

@echo off

setlocal EnableExtensions EnableDelayedExpansion

chcp 65001 > nul

color 0A

title String analysis

set /a Count=0

set /a Count+=1 & set String_!Count!="This is a test."
set /a Count+=1 & set String_!Count!="This_is_a_test."
set /a Count+=1 & set String_!Count!="        This is a test."
set /a Count+=1 & set String_!Count!="This is a test.        "
set /a Count+=1 & set String_!Count!="    This is a test.    "

set /a Start=1
set /a Step=1
set /a Stop=!Count!

set Separatorline=--------------------------------------------------------------------------------

echo !Separatorline! & echo. & echo Strings: & echo.

FOR /L %%X IN (!Start!,!Step!,!Stop!) do (

    echo %%X: !String_%%X! & echo.

)

echo !Separatorline! & echo. & echo Stringslengths: & echo.

FOR /L %%X IN (!Start!,!Step!,!Stop!) do (

    call :StringLength !String_%%X! , Length

    echo %%X: !Length! & echo.

)

echo !Separatorline! & echo. & echo Number of spaces in strings: & echo.

FOR /L %%X IN (!Start!,!Step!,!Stop!) do (

    call :SpaceCount !String_%%X! , NumberOfSpaces

    echo %%X: !NumberOfSpaces! & echo.

)

endlocal
 
pause&goto:eof

::==============================================================================

:StringLength StrVar , [RtnVar]

setlocal EnableExtensions EnableDelayedExpansion

set /a Length=0
set String="%~1#"

for %%P in ( 4096 2048 1024 512 256 128 64 32 16 8 4 2 1 ) do (

    if "!String:~%%P,1!" NEQ "" (
        
        set /a Length+=%%P      
        set String=!String:~%%P!

    )

)

endlocal & if "%~2" equ "" (echo !Length!) else set /a %~2=!Length!

exit /B 0

::==============================================================================

:SpaceCount StrVar , [RtnVar]

setlocal EnableExtensions EnableDelayedExpansion

set String="%~1"
set /a NumberOfSpaces=0
set /a Start=1
set /a Step=1
set /a Skip=0
set /a Keep=1

call :StringLength !String! , Length

if !Length! equ 0 goto End

set /a Stop=!Length!

FOR /L %%X IN (!Start!,!Step!,!Stop!) DO (

    call set Char=!!String:~!Skip!,!Keep!!!

    if "!Char!" == " " set /a NumberOfSpaces+=1
    
    set /a Skip+=1
    
)

:End

endlocal & if "%~2" equ "" (echo !NumberOfSpaces!) else set /a %~2=!NumberOfSpaces!

exit /B 0

::==============================================================================

:WordCount StrVar , [RtnVar]

setlocal EnableExtensions EnableDelayedExpansion

REM Not yet implemented.

endlocal

exit /B 0

::==============================================================================

:WordLength StrVar , WordNumber , [RtnVar_WordLen] , [RtnVar_StartPos] , [RtnVar_EndPos]

setlocal EnableExtensions EnableDelayedExpansion

REM Not yet implemented.

endlocal

exit /B 0
4
  • Why are you working with batch rather than PowerShell? social.technet.microsoft.com/Forums/en-US/… Commented Jun 22, 2020 at 18:42
  • I only learned that PowerShell existed pretty late, and it seemed like a big task to learn it. Besides there are many batch scripts out there, so it's a good thing to know your batch.
    – JKA1976
    Commented Jun 23, 2020 at 13:56
  • I only learned of it's existence pretty late, and it seemed like a big task to learn it.
    – JKA1976
    Commented Jun 23, 2020 at 14:00
  • You certainly find a lot of examples on the internet because it's been around forever. But you only need to know it if your job requires you to maintain old code. In PowerShell, this defines a string: '$a = 'Hello world. How many spaces?''. The length is a built-in property: $a.Length. This counts spaces: ([Char[]]$a).Where({ $_ -eq ' ' }).Count. Basic word count: ($a -split ' ').count. Sure, there's a learning curve, but it's worth it. Commented Jun 23, 2020 at 14:46

1 Answer 1

2

There is more to improve in your script. However, here is merely answer to your question.

For example in :StringLength function is the Length variable local hence !Length! is not more defined after endlocal at execution time:

endlocal & if "%~2" equ "" (echo !Length!) else set /a %~2=!Length!
rem                               ↑↑↑↑↑↑                    ↑↑↑↑↑↑

However, %Length% is still valid (defined in parsing time) so the line should be

endlocal & if "%~2" equ "" (echo %Length%) else set /a %~2=%Length%

Read more in SETLOCAL: Set options to control the visibility of environment variables in a batch file. and subsequent EnableDelayedExpansion:

Delayed Expansion will cause variables within a batch file to be expanded at execution time rather than at parse time, this option is turned on with the SETLOCAL EnableDelayedExpansion command.

1
  • Thank you very much JosefZ! Now I have something to work with!
    – JKA1976
    Commented Jun 22, 2020 at 16:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .