3

When you type, for example,

echo Variable "$var" is not initialised.

and

echo "Variable $var is not initialised."

the front end result is the exact same (as far as I know, at least). But I was wondering, from echo's perspective, if there are any difference on how the command is ran.

And performance-wise, is the latter faster, since echo would recieve all arguments at once?

Linkyu
  • 133
  • 5
  • 3
    In this case no, not really, as far as the output is concerned. In the first case echo gets 5 args and in the second 1 arg. But echo concats its args on spaces - a single space per - and so it prints the same. Both uses are perfectly safe. You would see the difference if you did echo "Variable $var is not initialised." though. – mikeserv Jan 09 '15 at 16:00
  • 3
    @mikeserv, that's the answer, why don't you post the answer? – glenn jackman Jan 09 '15 at 16:07
  • 2
    @mikeserv, with many echo implementations (including bash's under some circumstances), it's not safe in that escape sequences in $var will be expanded. Generally, you want printf to print arbitrary data. – Stéphane Chazelas Jan 09 '15 at 16:11
  • @StéphaneChazelas - very good point. I meant regarding $var's expansion as an argument. But I wasn't even considering the possibility of backslash escapes in the expansion. Then again, if there are such, they will at least be preserved for echo to interpret. But yes, for a literal representation of string the most reliable method of getting such is as an explicitly declared %string argument to printf. – mikeserv Jan 09 '15 at 16:33
  • @glennjackman partly because it is incorrect - but also because a comment would suffice. Feel free to write it up better - I'd happily upvote it if you expanded on it. – mikeserv Jan 09 '15 at 16:34
  • 3
    As for performance, I ran a few loops. There was about a 10% difference. Nothing to be excited about. – muru Jan 09 '15 at 23:35
  • @muru Ah! It's actually higher than I even expected, and it does actually answer part of my question; just to be sure, it was the latter that were faster, right? – Linkyu Jan 11 '15 at 18:01
  • @Linkyu yes, and I am rounding up to the nearest order-of-magnitude. – muru Jan 12 '15 at 03:26

1 Answers1

2

In

echo Variable "$var" is not initialised.

You're passing 5 arguments to echo (6 if you count echo, the argv[0]), echo will output them separated by a space character terminated with a newline.

In:

echo "Variable $var is not initialised."

You're passing 1 argument (2 if you count echo).

In this particular case and in most cases, that is going to be functionally equivalent.

The second means less work for the shell to parse the command and store it into arguments before running echo and less work for echo to go through its arguments.

That's unlikely to make a very significant difference in terms of performance. In my tests, I see it making a small difference with some echo/shell combinations like bash with its builtin, but hardly any in others.

Other reasons why you may want to pass one argument instead of several:

  • If you want more than a space between the arguments: echo a b would output a b, you need echo 'a b' to output a b.

  • In things like echo "$opt" is an invalid option, with some echo implementations like the echo builtin of bash, that wouldn't work with opt=-e (or -E or -neE...) while echo "$opt is an invalid option" would be OK.

  • In echo foo bar, you're passing 2 arguments (beside the echo one) 3 byte long each, that is 2 pointers (8 byte each on 64bit systems) and 8 bytes including the \0 string delimiters for the actual strings, so 24 bytes in total on 64bit systems.

    While it's one pointer and 8 bytes for echo 'foo bar' (16 bytes total). When calling the external echo executable with a large list of arguments, that can make you reach the limit on the size of the arguments sooner (though note that Linux also has a limit (128KiB) on the maximum size of a single argument).

In any case here, for arbitrary data (like that $var whose content we don't know (though from the context here we could derive that it contains only alnums and underscore)), you want to use printf, not echo:

printf >&2 '%s\n' "Variable $var is not initialised."

Or:

printf >&2 'Variable %s is not initialised.' "$var"

(here sent to stderr as that looks like it's meant to be an error to the user and not part of the normal output produced by your script).

And in that case, beside the format, it has to be one single argument passed to printf.

Another advantage of that approach is that it makes it possible to translate the messages in the user's language where you can provide ready made translations of that Variable %s is not initialised. format in all supported languages (and using gettext or ksh93/bash's $"..." to retrieve them).

  • One year and a half since I've posted this, but definitely worth the wait. Splendid answer! – Linkyu Aug 25 '16 at 19:25