j b
j b

Reputation: 51

count an exact character in one line - cmd

I would like write a batch file to count the number of occurrences of a specific character in each line of a text file.

For example, the count of \ in the string "aa\bb\cc\dd\" would be 4.

The find and the findstr show only the number of lines which is contains the exact character.

Upvotes: 5

Views: 5966

Answers (6)

Aacini
Aacini

Reputation: 67216

@echo off
setlocal

set "string=aa\bb\cc\dd\"

set "count=-1"
for %%a in ("%string:\=" "%") do set /A count+=1

echo %count%

This method works correctly as long as the string don't include wild-card characters: *?; if this is required, I would use the same npocmaka's method, but written in a simpler way:

@echo off
setlocal EnableDelayedExpansion

set "string=aa\bb\cc\dd\"

set "str=A%string%Z"
set "count=-1"
for /F "delims=" %%a in (^"!str:\^=^"^
% Do NOT remove this line %
^"!^") do (
  set /A count+=1
)
echo %count%

Upvotes: 4

Squashman
Squashman

Reputation: 14290

Not tested extensively but works with your example.

@ECHO OFF
SETLOCAL disabledelayedexpansion
SET "String=\a\b\c\\\\d\\"
set "previous=%string%"
set /a count=0
:loop
set "newstg=%previous:*\=%"
IF NOT "%previous%"=="%newstg%" (
    set /a count+=1
    set "previous=%newstg%"
    IF DEFINED previous goto loop
)
echo %count%
pause
GOTO :eof

Here is one more option. I don't think this is bullet proof with poison characters.

@ECHO OFF
SETLOCAL disabledelayedexpansion
SET "String=\\a\b\c\\\\d\\"
set i=0
set "x=%string%"
set "x=%x:\=" & set /A i+=1 & set "x=%"
echo %i%

pause

Upvotes: 2

MC ND
MC ND

Reputation: 70923

While slow, you can try with this

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "inputFile=input.txt"
    set "searchChar=\"

    for /f "delims=" %%a in ('
        findstr /n "^" "%inputFile%"
    ') do for /f "delims=:" %%b in ("%%~a") do (
        set "line=%%a"
        for /f %%c in ('
            cmd /u /v /e /q /c"(echo(!line:*:=!)"^|find /c "%searchChar%"
        ') do echo Line %%b has %%c characters
    )

The input file is readed using findstr /n to get all the lines in the file with a number prefix (both for output "decoration" and to ensure all the lines in the file are processed). Each line is processed inside a pipe, from cmd to find. The cmd instance is started with unicode output (/u) so when the readed line is echoed, the output will be a two bytes sequence for each input character, one of them a 0x0 ASCII character. The find command sees the 0 as a line terminator, so we get each character in the input line as one separated line. Now, the find command counts in how many lines the searched character happens.

Upvotes: 3

aschipfl
aschipfl

Reputation: 34909

You might try the following script, providing the input string as (quoted) command line argument:

set "STRING=%~1$"
set STRING="%STRING:\=" "%"
set /A "COUNT=-1"
for %%E in (%STRING%) do set /A "COUNT+=1"
echo Count of `\`: %COUNT%

This replaces every character to be counted by " + SPACE + " and encloses the entire string in between "", so the input string aa\bb\cc\dd\ becomes "aa" "bb" "cc" "dd" "". The resulting string is fed into a for loop that recognises individual items to iterate through -- five in this case. The counter variable COUNT is initialised with a value of -1, so the result is not the number of iterated items but the separators, namely the \ characters present in the original string.

This approach fails if the string contains ? or * characters. It would also fail in case the character to count is one of the following: ", %, =, *, ~.

Upvotes: 4

npocmaka
npocmaka

Reputation: 57252

here's one way:

 @echo off
:checkCountOf string countOf [rtnrVar]
:: checks count of a substring  in a string 
setlocal EnableDelayedExpansion
set "string=aa"

set "string=%~1"
set "checkCountOf=%~2"

if "%~1" equ "" (
    if "%~3" neq "" (
        endlocal & (
           echo 0
           set "%~3=0"
           exit /b 0
        )
    ) else (
        endlocal & (
           echo 0
           exit /b 0
        )
)


)

if "!checkCountOf!" equ "$" (
    set "string=#%string%#"
    set "string=!string:%checkCountOf%%checkCountOf%=#%checkCountOf%#%checkCountOf%#!"
) else (
    set "string=$%string%$"
    set "string=!string:%checkCountOf%%checkCountOf%=$%checkCountOf%$%checkCountOf%$!"
)


set LF=^


rem ** Two empty lines are required
set /a counter=0


for %%L in ("!LF!") DO (
    for /f "delims=" %%R in ("!checkCountOf!") do ( 
        set "var=!string:%%~R%%~R=%%~L!"
        set "var=!var:%%~R=%%~L!"

        for /f "tokens=* delims=" %%# in ("!var!") do (
            set /a counter=counter+1
        )
    )
)

if !counter! gtr 0 (
    set /a counter=counter-1
)

if "%~3" neq "" (
    endlocal & (
       echo %counter%
       set "%~3=%counter%"
    )
) else (
    endlocal & (
       echo %counter%
    )
)

you can call it like:

call ::checkCountOf "/aa/b/c/" "/" slashes
echo %slashes%
exit /b %errorlevel% 

wont work with some special characters (",~ and !)

You can also use replacement and the :strlen function

Upvotes: 2

Magoo
Magoo

Reputation: 80023

@ECHO OFF
SETLOCAL
SET "String=a\b\c\\\\d"
CALL :count "%string%" \
ECHO %tally%
GOTO :EOF

:count
SETLOCAL enabledelayedexpansion
SET /a tally=0
SET "$2=%~1"
:cloop
SET "$1=%$2%"
SET "$2=!$1:*%2=!"
IF "%$1%" neq "%$2%" SET /a tally+=1&GOTO cloop
endlocal&SET tally=%tally%
GOTO :eof

Here's a way to count particular characters in a string. It won't work for the usual suspects.

Upvotes: 2

Related Questions