Reputation: 51
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
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
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
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
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
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
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