Subject: Re: bug#20954: wc - linux

From: Bob Proulx <[email-masked]>
Date: Thu, 2 Jul 2015 17:33:23 -0600

tele wrote:
> "echo" gives in new line,

Yes.

> "echo -n" subtracts 1 line,

echo -n is non-portable and shouldn't be used.

echo -n suppresses emitting a trailing newline.

Note that in both of these cases you are using the shell's internal
builtin echo and not the coreutils echo.  They behave the same.

> but "wc -l" can count only from new line, so if something exist
> inside first line "wc -l" can not count. :-(

"wc -l" counts newlines.  That is the task that it was constructed to
do.  That is exactly what it does.  No more and no less.

What is a text line?  A text line by definition ends with a newline.
This has been standardized to prevent different implementations from
implementing it differently and creating portability problems.
Therefore all standards compliant implementations must implement it in
the same way to prevent portability problems.

> example:
>
>	$ a="j" ; echo  "$a"  |  wc -l
>	1

I have been wondering.  Why are you using a variable here?  Using the
variable as you are doing is no different than not using the variable.

  echo "j" | od -tx1 -c
  0000000  6a  0a
            j  \n

There is one newline.  That counts as one text line.

>	$ a="" ; echo  "$a"  |  wc -l
>	1

  echo "" | od -tx1 -c
  0000000  0a
           \n

There is one newline.  That counts as one text line.

>	$ a="" ; echo -n "$a"  |  wc -l
>	0

  echo -n "" | od -tx1 -c
  0000000

Nothing was emitted.  No newlines.  Counts as zero lines.  But nothing
was emitted.  Zero characters.

  od -tx1 -c < /dev/null
  0000000

>	$ a="j" ; echo -n "$a"  |  wc -l
>	0

  echo -n "j" | od -tx1 -c
  0000000  6a
            j

That emits one character, the 'j' character.  It emits no newlines.
Without any newlines at all that is not and cannot be a "text" line.
Without a newline that can only be interpreted as binary data.  In any
case there were no newlines to count and "wc -l" counted and reported
zero newlines.

Instead of echo -n it would be better and portable to use printf
instead.

  printf "j" | od -tx1 -c
  0000000  6a
            j

Same action in a portable way using printf.  Avoid using echo with
options.

> So,
> 
> $ a="" ; echo  "$a"  |  sed '/^\s*$/d' | wc -l
> 0

  echo "" | sed '/^\s*$/d' | od -tx1 -c
  0000000

As we previosuly see the echo action will emit one newline character.
This is piped to the sed program which will delete that line.
Deleting the line is what the sed 'd' action does.  Therefore sed does
not emit the newline.  The text line is deleted.

> $ a="3" ; echo  "$a"  |  sed '/^\s*$/d' | wc -l
> 1

  echo "3" | sed '/^\s*$/d' | od -tx1 -c
  0000000  33  0a
            3  \n

Here the echo emitted two character a '3' and a newline.  The sed
prgram did not match and therefore did not delete the line.  Since it
did not delete the line it passed the one text line to wc and "wc -l"
counted the one newline and reported one text line.

> Can be added option to "wc" to fix this problem without use sed in future ?
> Thanks for helping :-)

There is no problem to be fixed.  And therefore this isn't something
that can be "fixed" in wc.

Bob