## 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%