Skip to main content
added 674 characters in body
Source Link
Neil
  • 184.4k
  • 12
  • 76
  • 290

Empty strings and quotes can even be handled for 212 bytes without resorting to file length builtins:

@set s= @set/ps= @set "t=%s:"=""%" @set n=0 @if "%t:"=""%"=="""=""""" goto g :l @set/an+=1 @set "s=%t:~,1%%t:~,1%" @if "%s%" neq """" set "t=.%t%" @set "t=%t:~2%" @if not "%t%"=="" goto l :g @echo %n% 

Here after quoting the quotes in s we have to be careful to double the first character of t in case it is a quote, then if it is not then prefix a dummy character to t so that the first two characters may be safely removed. This ends up counting the quoted quotes as single characters again.

Empty strings and quotes can even be handled for 212 bytes without resorting to file length builtins:

@set s= @set/ps= @set "t=%s:"=""%" @set n=0 @if "%t:"=""%"=="""=""""" goto g :l @set/an+=1 @set "s=%t:~,1%%t:~,1%" @if "%s%" neq """" set "t=.%t%" @set "t=%t:~2%" @if not "%t%"=="" goto l :g @echo %n% 

Here after quoting the quotes in s we have to be careful to double the first character of t in case it is a quote, then if it is not then prefix a dummy character to t so that the first two characters may be safely removed. This ends up counting the quoted quotes as single characters again.

added 1200 characters in body
Source Link
Neil
  • 184.4k
  • 12
  • 76
  • 290

Batch, 117182 bytes

@set s= @set/ps= @set "t=%s:"=""%" @if "%t:"=""%"=="""=""""" goto g @for %%s in ("%s:"=%" "%s:"=""%""%t%")do @echo(%%~s>>_ @for %%s in (_)do @set s=%%~zs @del _ :g @cmd/cset/as/2-22*!!s 

Doesn't workTesting for the empty string without breaking when quotes were present was cumbersome! Explanation:

@set s= 

Clear s as set/p leaves s unchanged if the input was empty.

@set/ps= 

Take input on STDIN into s.

@set "t=%s:"=""%" 

Try to quote all of the quotes in s. However, because there's no safe wayif s is empty, Batch throws a wobbly, and sets t to detect it"="" instead, which still has an odd number of quotes. Works by printing

@if "%t:"=""%"=="""=""""" goto g 

Quote all of the string twicequotes in t, onceand compare the result to ""="""". This can only happen if s was empty, in which case we skip the measurement step.

@for %%s in ("%s:"=%" "%t%")do @echo(%%~s>>_ 

Print s without quotes, once and s with quoted quotes doubled, then taking the resultingon separate lines to a temporary file. The ( is needed in case s only contains quotes.

@for %%s in (_)do @set s=%%~zs 

Obtain the length, dividing by of the temporary file.

@del _ 

Delete the temporary file.

:g 

Jump here if the input was empty.

@cmd/cset/as/2-2*!!s 

Halve and subtract 2 from the length of the temporary file. However if the input was empty then s will be treated as the numeric value zero, and subtracting 2 for the CRLFresult of the expression is then zero as desired.

117 bytes without empty string support:

@set/ps= @for %%s in ("%s:"=%" "%s:"=""%")do @echo(%%~s>>_ @for %%s in (_)do @set s=%%~zs @del _ @cmd/cset/as/2-2 

93 bytes if support for "s is not necessary, in which case the empty string can be supported (84 bytes without " or empty string support):

@set s= @set/ps= @set n=0 :l @if not "%s%"=="" set/an+=1&set "s=%s:~1%"&goto l @echo %n% 

Batch, 117 bytes

@set/ps= @for %%s in ("%s:"=%" "%s:"=""%")do @echo(%%~s>>_ @for %%s in (_)do @set s=%%~zs @del _ @cmd/cset/as/2-2 

Doesn't work for the empty string, because there's no safe way to detect it. Works by printing the string twice, once without quotes, once with quotes doubled, then taking the resulting file length, dividing by 2, and subtracting 2 for the CRLF. 93 bytes if support for "s is not necessary, in which case the empty string can be supported (84 bytes without empty string support):

@set s= @set/ps= @set n=0 :l @if not "%s%"=="" set/an+=1&set "s=%s:~1%"&goto l @echo %n% 

Batch, 182 bytes

@set s= @set/ps= @set "t=%s:"=""%" @if "%t:"=""%"=="""=""""" goto g @for %%s in ("%s:"=%" "%t%")do @echo(%%~s>>_ @for %%s in (_)do @set s=%%~zs @del _ :g @cmd/cset/as/2-2*!!s 

Testing for the empty string without breaking when quotes were present was cumbersome! Explanation:

@set s= 

Clear s as set/p leaves s unchanged if the input was empty.

@set/ps= 

Take input on STDIN into s.

@set "t=%s:"=""%" 

Try to quote all of the quotes in s. However, if s is empty, Batch throws a wobbly, and sets t to "="" instead, which still has an odd number of quotes.

@if "%t:"=""%"=="""=""""" goto g 

Quote all of the quotes in t, and compare the result to ""="""". This can only happen if s was empty, in which case we skip the measurement step.

@for %%s in ("%s:"=%" "%t%")do @echo(%%~s>>_ 

Print s without quotes and s with quoted quotes on separate lines to a temporary file. The ( is needed in case s only contains quotes.

@for %%s in (_)do @set s=%%~zs 

Obtain the length of the temporary file.

@del _ 

Delete the temporary file.

:g 

Jump here if the input was empty.

@cmd/cset/as/2-2*!!s 

Halve and subtract 2 from the length of the temporary file. However if the input was empty then s will be treated as the numeric value zero, and the result of the expression is then zero as desired.

117 bytes without empty string support:

@set/ps= @for %%s in ("%s:"=%" "%s:"=""%")do @echo(%%~s>>_ @for %%s in (_)do @set s=%%~zs @del _ @cmd/cset/as/2-2 

93 bytes if support for "s is not necessary (84 bytes without " or empty string support):

@set s= @set/ps= @set n=0 :l @if not "%s%"=="" set/an+=1&set "s=%s:~1%"&goto l @echo %n% 
Source Link
Neil
  • 184.4k
  • 12
  • 76
  • 290

Batch, 117 bytes

@set/ps= @for %%s in ("%s:"=%" "%s:"=""%")do @echo(%%~s>>_ @for %%s in (_)do @set s=%%~zs @del _ @cmd/cset/as/2-2 

Doesn't work for the empty string, because there's no safe way to detect it. Works by printing the string twice, once without quotes, once with quotes doubled, then taking the resulting file length, dividing by 2, and subtracting 2 for the CRLF. 93 bytes if support for "s is not necessary, in which case the empty string can be supported (84 bytes without empty string support):

@set s= @set/ps= @set n=0 :l @if not "%s%"=="" set/an+=1&set "s=%s:~1%"&goto l @echo %n%