Powershell, 123 bytes
switch -r($args|% t*y){'\s'{$a=0}'\S'{$w+=!$a;$a=1}'(?s).'{$b++}'
'{$l++}}
$c="$b".Length
"{0,$c} {1,$c} {2,$c}"-f$l,+$w,$b
Test script:
$f = {
switch -r($args|% t*y){ # evaluate all matched cases
'\s' {$a=0} # any whitespace (newline not included)
'\S' {$w+=!$a;$a=1} # any not-whitespace (newline not included)
'(?s).'{$b++} # any char (newline included!)
'`n' {$l++} # new line char
}
$c="$b".Length
"{0,$c} {1,$c} {2,$c}"-f$l,+$w,$b
}
@(
, ("a b c d`n", "1 4 8")
, ("a b c d e f`n", " 1 6 12")
, (" a b c d e f `n", " 1 6 16")
, ("a`nb`nc`nd`n", "4 4 8")
, ("a`n`n`nb`nc`nd`n", " 6 4 10")
, ("abc123{}[]()...`n", " 1 1 16")
, ("`n", "1 0 1")
, (" `n", "1 0 4")
, ("`n`n`n`n`n", "5 0 5")
, ("`n`n`na`nb`n", "5 2 7")
) | % {
$s,$e = $_
$r = &$f $s
"$($e-eq$r): $r"
}
Output:
True: 1 4 8
True: 1 6 12
True: 1 6 16
True: 4 4 8
True: 6 4 10
True: 1 1 16
True: 1 0 1
True: 1 0 4
True: 5 0 5
True: 5 2 7
Explanation:
$args|% t*y
splits arument strings into chars
switch -r($args|% t*y)
evaluate all matched cases
'\s'
case for any whitespace
'\S'
case for any non-whitespace
'(?s).'
case for any char (newline included)
'\n'
case for newline char (newline represent itself)
$c="$b".Length
calculate a length of bytes number. $b is always max($l,$w,$b) by design
"{0,$c} {1,$c} {2,$c}"-f$l,+$w,$b
format numbers with same length. The variable $w converts to int. It need for strings without words. Other variables format 'as is' because $l and $b cannot be 0 because 'The input will always contain a trailing newline'.