Delete Consecutive repeating characters

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Delete Consecutive repeating characters

#1 Post by Squashman » 20 Aug 2012 19:36

Was helping out on another forum. All the original poster wanted was to make sure that there was never more than 3 repeating characters in his string. His string would never be more than 15 characters long so that is why my loop is set for 0 to 11. I am sure this script would also fail with special characters.

So I initially came up with this:

Code: Select all

@echo off
setlocal enabledelayedexpansion

set var=SssstoOoormUUUu
echo input string is: %var%
FOR /L %%G in (0,1,11) do call :parse %%G
echo final string is: %var%
Pause
goto :eof

:parse
set N1=%~1
set /a N2=%~1+1
set four=!var:~%N1%,4!
set three=!var:~%N1%,3!
IF /I "!var:~%N1%,3!"=="!var:~%N2%,3!" set var=!var:%four%=%three%

Which outputs this:

Code: Select all

input string is: SssstoOoormUUUu
final string is: SsstoOormUUU

But then I thought to myself. This could really be a pretty cool function if it was more flexible.
Would need to be able to pass to it how many repeating characters you really wanted within your string and could it be made flexible enough to not have to know what the initial string length was and I assume we would have the usual issues if the string had special characters in it.
Not sure if this has been done already or not. Couldn't find anything in the library but maybe I missed it.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Delete repeating characters

#2 Post by foxidrive » 20 Aug 2012 21:10

Not knowing the background - but what if the string was

AbAcA

which has three repeating A characters. And then you have to cater for character case such as "A" and "a".

If it's just three consecutive characters of the same case then it's more straight forward, but it's not the sort of thing I've ever seen being asked before. :)

Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Re: Delete repeating characters

#3 Post by Squashman » 20 Aug 2012 21:20

foxidrive wrote:Not knowing the background - but what if the string was

AbAcA

which has three repeating A characters. And then you have to cater for character case such as "A" and "a".

If it's just three consecutive characters of the same case then it's more straight forward, but it's not the sort of thing I've ever seen being asked before. :)

Consecutive repeating characters.
AAAABBBBCCCC
AAABBBCCC

string replacement in batch is case insensitive. Don't want to worry about that at this point.

Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Re: Delete Consecutive repeating characters

#4 Post by Squashman » 20 Aug 2012 21:50

A bit more flexible.

Code: Select all

@echo off

call :parse 2 SssstoOoormUUUUu
Pause
goto :eof

:parse
setlocal enabledelayedexpansion
set var=%~2
set N1=%~1
set /a N2=%~1+1
set p1=0

:iLoop
set /a p2=p1+1
set replace=!var:~%p1%,%N2%!
set change=!var:~%p2%,%N1%!
IF /I "!var:~%p1%,%~1!"=="!var:~%p2%,%~1!" set var=!var:%replace%=%change%!
IF /I NOt "!var:~%p1%,%~1!"=="!var:~%p2%,%~1!" set /a p1+=1
IF NOT "!var:~%p2%!"=="" GOTO :iLoop
echo %var%
goto :EOF

Parse 2 outputs: sstoormUu
Parse 1 outputs: stOrmu

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Delete Consecutive repeating characters

#5 Post by dbenham » 20 Aug 2012 22:59

Here is a routine that is efficient and can process any string containing any values (except 0x00 NULL of course). It uses the DOSTips strLen function.

The result can optionally be returned in a variable instead of ECHOing to the screen.

Values containing Carriage Return and/or New Line are OK to print, but they will not be returned properly in a variable. The function can be extended to support returning Carriage Return and/or New Line.

The function is safe to call with delayed expansion enabled or disabled.

Code: Select all


@echo off
:limitRepeats  strVar  maxRepeat  [rtnVar]
::
:: Limit the number of repeating consecutive characters
::
::   strVar = Name of variable that contains the string
::
::   maxRepeat = The maximum number of repeats allowed.
::               Any value <1 is treated as 1
::
::   rtnVar = Optional name of variable to return result in.
::            The result is echoed if rtnVar not specified.
::
:: The function is safe to call with delayed expansion enabled
:: or disabled.
::
  setlocal
  set "NotDelayed=!"
  setlocal enableDelayedExpansion
  set "str=!%~1!"
  set /a "max=%~2"
  set "chr="
  set "rtn="
  call :strLen str len
  for /l %%N in (0 1 %len%) do (
    set "next=!str:~%%N,1!"
    if "!next!" == "!chr!" (
      if !cnt! lss !max! (
        set "rtn=!rtn!!next!"
        set /a cnt+=1
      )
    ) else (
      set "rtn=!rtn!!next!"
      set "chr=!next!"
      set cnt=1
    )
  )
  if "%~3" == "" (
    echo(!rtn!
    exit /b
  )
  :: Safely return the
  set "rtn=!rtn:%%=%%A!"
  set "rtn=!rtn:"=%%B!"
  if not defined NotDelayed set "rtn=!rtn:^=^^^^!"
  if not defined NotDelayed set "rtn=%rtn:!=^^^!%" !
  for /f "usebackq tokens=1,2" %%A in ('%%^ ^"') do (
    endlocal & endlocal
    set "%~3=%rtn%" !
  )
exit /b


:strLen string len -- returns the length of a string
::                 -- string [in]  - variable name containing the string being measured for length
::                 -- len    [out] - variable to be used to return the string length
:: Many thanks to 'sowgtsoi', but also 'jeb' and 'amel27' dostips forum users helped making this short and efficient
:$created 20081122 :$changed 20101116 :$categories StringOperation
:$source http://www.dostips.com
(   SETLOCAL ENABLEDELAYEDEXPANSION
    set "str=A!%~1!"&rem keep the A up front to ensure we get the length and not the upper bound
                     rem it also avoids trouble in case of empty string
    set "len=0"
    for /L %%A in (12,-1,0) do (
        set /a "len|=1<<%%A"
        for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"
    )
)
( ENDLOCAL & REM RETURN VALUES
    IF "%~2" NEQ "" SET /a %~2=%len%
)
EXIT /b


Dave Benham

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Delete Consecutive repeating characters

#6 Post by foxidrive » 21 Aug 2012 03:16

dbenham wrote:Here is a routine that is efficient and can process any string containing any values (except 0x00 NULL of course). It uses the DOSTips strLen function.


Any value? It seems to have issues with a usual poison character, like ^

Code: Select all

@echo off
set "b=!!^aa!a!!!"
echo "%b%"
call :limitrepeats b 3 a
echo %a%
pause
goto :eof



"!!^aa!a!!!"
!!aa!a!!!

Press any key to continue . . .

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Delete Consecutive repeating characters

#7 Post by Ed Dyreen » 21 Aug 2012 03:37

'
morning Foxi, hot innit :wink:
foxidrive wrote:
dbenham wrote:Here is a routine that is efficient and can process any string containing any values (except 0x00 NULL of course). It uses the DOSTips strLen function.


Any value? It seems to have issues with a usual poison character, like ^

Code: Select all

@echo off
set "b=!!^aa!a!!!"
echo "%b%"
call :limitrepeats b 3 a
echo %a%
pause
goto :eof



"!!^aa!a!!!"
!!aa!a!!!

Press any key to continue . . .
It works as expected.

Code: Select all

@echo off

set "b=!!^aa!abbbb!!!"
echo "%b%"

call :limitrepeats b 3 a

echo.
echo "%a%"

echo.notDelayed ! but still strips the ^caret or ?^^

pause
exit

Code: Select all

"!!^aa!abbbb!!!"

"!!^aa!abbb!!!"
notDelayed ! but still strips the caret or ?^
Druk op een toets om door te gaan. . .

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Delete Consecutive repeating characters

#8 Post by foxidrive » 21 Aug 2012 04:14

Winter here, but get's mighty hot in summer.



The problem was my doing - I echoed the variable without quotes.

Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Re: Delete Consecutive repeating characters

#9 Post by Squashman » 21 Aug 2012 06:10

Dave deserves a Library entry for that. Maybe put it into the DOS String Operations category.

Post Reply