From: Seebs on
On 2010-04-13, houghi <houghi(a)houghi.org.invalid> wrote:
> It is is all that I need. Still unsure why the printf is better then the
> echo as the result is the same, but I take your word for it.

Using printf lets you do many things that echo can't do, and even some
of the simpler ones are things which echo can't do *portably*, because
of the historical clash between \c and -n.

>> "Format string" is a normal string,

> This is already getting difficult for me.

Okay, here's the idea.

"printf" is "print formatted". What it lets you do is specify, separately:

1. How you want stuff to look.
2. What stuff you want to look like that.

Here's an example:

$ printf "%s\n" "foo"
foo
$ printf "%5s\n" "foo"
foo
$ printf "%5d\n" 23
23
$ printf "%-5d %s\n" 23 "foo"
23 foo

What this is useful for is that you can control the display of
things, by modifying formats (%... is a format specifier).

> And here you lost me. Sorry. I read it several times. Read it out loud.
> I understand what the words mean, but somehow they do not get together
> as something meaningfull.

Do you have any concepts of things like "templates" or "forms"? The
purpose of "printf" is to let you specify the template/form separately
from the data.

>> printf "The sum of %d and %d is %d.\n" "$num1" "$num2" "$((num1+num2))"

>> If $num1 is 4, and $num2 is 5, the above prints

>> The sum of 4 and 5 is 9.

> I can copy and paste it, but I have no idea what I am doing, sorry. That
> means I could do somtjing identical, but when it is a bit different, I
> am lost. I guess it is because the order of things is different.

> With echi I would first name $num1, then $num2 and then do whatever I
> like with them. I just seem unable to get my head around first telling
> what you want and then afterwards fill in the blanks.

Well, you just described it exactly. That's what happens.

> I know that is not everything, but that is how _I_ see it. To me that
> feels impossible I have no idea yet what %d will be, let alone how many
> %d I will need, so how can I determine what I should write down.

You need however many you want to display. (Actually, there's some weirdness
to what shell printf does with extra arguments; ignore it for now.)

Look, imagine that you were gonna write:

echo "The sum of $num1 and $num2 is $((num1 + num2))"

Where do you need to interpolate values into the string? Where the $
signs are.

So.

printf "The sum of %d and %d is %d" ...

Okay, what goes next? Well, what value do you want in the first spot?
You want "$num1", because that's the value you were printing:

printf "The sum of %d and %d is %d" $num1 ...

Okay, what goes in the second spot? $num2:

printf "The sum of %d and %d is %d" $num1 $num2 ...

And the third spot?
printf "The sum of %d and %d is %d" $num1 $num2 $((num1 + num2))

There you have it.

Now, why would you do this?

Imagine:

for i in 1 10 100; do
echo "$i bottles of beer on the wall..."
done

1 bottles of beer on the wall...
10 bottles of beer on the wall...
100 bottles of beer on the wall...

Oh, that's annoying, it doesn't line up. We want it to line up.

With echo, you can do something elaborate to try to work around
this. With printf:

printf "%3d bottles of beer on the wall..." $i

and you get
1 bottles of beer on the wall...
10 bottles of beer on the wall...
100 bottles of beer on the wall...

It controls *formatting*.

> And there lies my limitation. I have read many man pages. However I
> seldom understand what they mean. I understand the words, but very
> seldom the meaning.

That's come across some. Do you usually have trouble abstracting things
from examples to general patterns?

>
> I read the 4 manpages and the info page and I have now even less
> understanding. Again, it is _my_ limitations. I do understand that it is
> very simple for most people. I just seem unable to get my head around
> it. e.g. it says:
> Thus,
> printf("%'.2f", 1234567.89);
> results in "1234567.89" in the POSIX locale, [...]
>
> And I get:
> houghi(a)penne : printf ("%'.2f", 1234567.89);
> bash: syntax error near unexpected token `"%'.2f",'

That's because you're reading the man page for a DIFFERENT thing called
"printf". You're looking at the man page for the C function.

You should be able to spot that, because in shell, you don't use () like
that.

I'm not sure how to explain why this ought to be obvious, but in general,
I would expect that, when you had five or ten examples none of which used
() or ended lines with ;, and you saw a new example which used () and
ended a line with ;, I guess that would be something I'd expect to make you
think "hey, this looks different".

> I also know that many people do not understand or even do not believe me
> that I can't grasp so many things. I will try to remember if I post
> something here to replace the echo command with the printf, so not to
> offend anybody.

That won't work until you figure out how printf works.

I guess the second question is... What are your goals? Is this purely a
hobby? Are you aiming for a job doing this stuff? How much it matters
whether you understand what you're doing depends somewhat on why you're
doing it.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
From: Seebs on
On 2010-04-13, thdyoung(a)googlemail.com <thdyoung(a)googlemail.com> wrote:
> i don't want to interfere but folk shy away from man pages coz they're
> so darned bad to read

No, they really aren't.

> face it - a miraculous habit has been widely established on the net
> via groups and BBs of helping each other:

Yes, and doing it as inefficiently as possible.

> rolling it back w sharp
> reproofs about reading the man pages is kind of counter-counter
> cultural.

Maybe, but it's also *right*. We have finite time. Spend it wisely,
and don't spend other people's time cheaply just because it's not your
time.

> all us lurkers glean vast amounts of learning from these groups - of
> course, we do: we are here to learn coz it is far better than the man
> pages

It's not better, it's *different*. It's aimed at solving a different kind
of problem. Failing to read the man pages first is insulting and rude; it's
a statement to everyone else that ten seconds of the time of every single
other reader in the newsgroup, and a minute or more from a few of them, is
worth much less than five minutes of your time.

I read and participate in these groups because I want to help people who have
shown a willingness to put in time and effort to learn, and want a hand with
it. I'm not here to help people who are too busy to put any of their own
time into learning. And with that, *plonk*.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
From: Janis Papanagnou on
houghi schrieb:
> pk wrote:
[...]
>
>> The general format of printf is
>>
>> printf <format string> <arguments>
>
> OK.
>
>> "Format string" is a normal string,
>
> This is already getting difficult for me.

The format string will define the output format; it will be interpreted and
expressions like %s or %d are like variables or placeholders for subsequent
arguments; %s will be replaced by a string, %d will be replaced by a number.

printf "+++ %s +++ %d +++\n" "Hello" "5"

will result in

+++ Hello +++ 5 +++

Instead of "Hello" and "5" you can expand variables which contain strings or
numbers. You can have an arbitrary amount of such % placeholders, just make
sure you have one argument for each placeholder following the format string.

>
>> but it contains some special sequences
>> that are special to printf, called "format specifications".
>
> Grasping on here.
>
>> "%s" above is
>> one of those. When printf sees one of those sequences, it replaces it with
>> the next argument in its list, and formats it accordingly. It follows that
>> (usually) if the format string contains n format specifications, you have to
>> supply n arguments to printf after the format string. For example, the
>> format specification %d is to print integers, so you do this:
>
> And here you lost me. Sorry. I read it several times. Read it out loud.
> I understand what the words mean, but somehow they do not get together
> as something meaningfull.

Is the above example probably more clear than pk's textual explanation?

>
>> printf "The sum of %d and %d is %d.\n" "$num1" "$num2" "$((num1+num2))"
>>
>> If $num1 is 4, and $num2 is 5, the above prints
>>
>> The sum of 4 and 5 is 9.
>
> I can copy and paste it, but I have no idea what I am doing, sorry. That
> means I could do somtjing identical, but when it is a bit different, I
> am lost. I guess it is because the order of things is different.

In the format string you have three placeholders %d for decimal numbers.
The arguments that follow will be substituted, one argument for one
placeholder, from left to right. "$num1" will be evaluated and fills the
first %d, "$num2" fills the second %d, and "$(( $num1 + $num2 ))" is an
arithmetic expression that will be evaluated by the shell, and then it
fills the third %d.

>
> [...] To me that
> feels impossible I have no idea yet what %d will be, let alone how many
> %d I will need, so how can I determine what I should write down.

%d is a placeholder for a decimal number argument that folows.
You need one % placeholder for each argument. (Simplified speaking.)

>
>> The format specifications are many, %s and %d are just two of them.
>> Simplifying, %s is for strings, %d for integers, %f and %g for floating
>> point numbers, %c for characters, %% for a literal %. There are many others,
>> and also each specification can have optional modifiers that change the
>> formatting. For example, %5d is like %d, but uses five characters to print
>> the integer, even if it's shorter (pads with spaces); likewise, %05d pads
>> with zeros.
>
> Sorry. Way over my head.

Besides %s and %d there are placeholders for other data types and their
formatted output. You don't need that in the beginning. Here's one more
set of examples, please try them out (the +++ is just for you to see
where the %05d, %5d, and %d, begins and ends)

printf "+++%05d+++\n" 5
printf "+++%5d+++\n" 5
printf "+++%d+++\n" 5

>
>> Printf has another advantage over echo: it recognizes many special escape
>> sequences that echo does not recognize (or recognizes only with -e in
>> certain implementations), like \n or \t.
>
> I understand that. That is why I avoid getting in such situations.

Sometimes you cannot avoid that situation. (If your echoed variables have
been filled by arbitrary user input or output from another process that
you read into the variable and that contains those characters.) Believe it.

>
>> [...]
>
> And there lies my limitation. I have read many man pages. However I
> seldom understand what they mean. I understand the words, but very
> seldom the meaning. even with `man date` I need to look at some part of
> the code I have already done previously to look what I need to do and
> even then try out all the options to see what is going on.

Then google for "<whatever> examples". You can certainly find a lot. I am
positive that examples from books and from the Web will help you; before
you start to experiment how randomly collected shell code works.

>
>> In case you
>> shell's man page for printf if scant, I suggest you do "man 3 printf" to see
>> the C printf man page with the full specs, to which the shell's printf is
>> mostly compliant (with the obvious differences/limitations).
>
> I read the 4 manpages and the info page and I have now even less
> understanding.

It was prabably an advice that you cannot use on your comprehension level.

> Again, it is _my_ limitations. I do understand that it is
> very simple for most people. I just seem unable to get my head around
> it. e.g. it says:
> Thus,
> printf("%'.2f", 1234567.89);

This is syntax for the "Programming Language C". While

printf "%'.2f" 1234567.89

is syntax for the shell programming languages.


> results in "1234567.89" in the POSIX locale, [...]

(ignore that part about POSIX locales for now)

>
> [...]
>
> I also know that many people do not understand or even do not believe me
> that I can't grasp so many things. I will try to remember if I post
> something here to replace the echo command with the printf, so not to
> offend anybody.

I, meanwhile, believe you and understand that you have problems with the
shell (or programming, or [English] language) concepts.

Just curious; why do you try to do shell programming at all? There are
certainly many much better suited programming languages with less pitfalls
and inconsistencies than you'll meet in the shell language.

Janis

>
> houghi
From: Seebs on
On 2010-04-13, houghi <houghi(a)houghi.org.invalid> wrote:
> Seebs wrote:
>> Using printf lets you do many things that echo can't do, and even some
>> of the simpler ones are things which echo can't do *portably*, because
>> of the historical clash between \c and -n.

> Again I believe what you say, although I have no idea what it means.

Let me see if I can simplify it.

On different systems, the "echo" command does different things.

Because of this, there are some things that it is very hard to write
so they will behave the same way on different computers. For instance,
my laptop and my desktop do not have the same behavior for "echo".

>> Okay, here's the idea.

>> "printf" is "print formatted". What it lets you do is specify, separately:

>> 1. How you want stuff to look.

> dasicaly just the output of $foo

Slow down. I'm not talking about just this one circumstance. I'm
explaining what printf does *IN GENERAL*.

The point of printf is that you can change how something is displayed.

>> $ printf "%-5d %s\n" 23 "foo"
>> 23 foo

> Whoosh!. Sorry.

Okay, let's walk through it.

"%-5d %s\n"

We see the first '%'. That means that we're going to find instructions
for how to display something. We start reading...
% <-- we're going to format something
- <-- it will be left-justified ("foo " instead of " foo")
5 <-- it will be printed 5 characters wide
d <-- ah-hah! We are printing a number

We now have instructions: "Print, left-justified, taking 5 spaces,
as a number..."

So we take the next argument (the first argument after the format string),
which is "23". We convert it to a number, and print it out, and get
"23 ".

Now we find a space. It's not a %, so we just print it, so we have
"23 ".

Now we find another %. Let's walk through this...
% <-- we are going to format something
s <-- it will be a string

Okay, we'll print the next argument as a string. The next argument is
"foo". So we print it, and we're now to "23 foo".

Then we see a \ and an n, and that's a newline, so we print "23 foo"
and then a newline.

>> What this is useful for is that you can control the display of
>> things, by modifying formats (%... is a format specifier).

> Very seldom do I need to format the output. I just need to do an `echo
> $foo` variation.

But sometimes you run into things like, say, wanting to print things
without starting a new line. There are at least two ways to do that with
echo, maybe three, but you can't be sure that what works on one machine
will work on another, so none of them are *reliable*.

>> Do you have any concepts of things like "templates" or "forms"? The
>> purpose of "printf" is to let you specify the template/form separately
>> from the data.

> No, sorry. I never needed to specify anything.

You've never in your life encountered a form which had data in it?
Done any kind of combination of data with output?

Do you know how to start a letter?

Dear Houghi,

What's happening there? We have a template:

Dear <name>,

and then we want to insert a value (the recipient's name) into the spot
where <name> is.

>> You need however many you want to display. (Actually, there's some weirdness
>> to what shell printf does with extra arguments; ignore it for now.)

> I almost never know that up front.

I can't comprehend this.

You want to display output. By the fact that you have some idea
what you want to display, you *ABSOLUTELY MUST* know what you want
to display. You can't write an "echo" command without knowing what
you want to display either.

>> Look, imagine that you were gonna write:
>>
>> echo "The sum of $num1 and $num2 is $((num1 + num2))"
>>
>> Where do you need to interpolate values into the string? Where the $
>> signs are.
>
> I would most likely do something like:
> #!/bin/bash
> NUM1=1
> NUM2=2
> let "TOTAL = $NUM1 + $NUM2"
> echo "The sum of $NUM1 and $NUM2 is $TOTAL"
>
> That way the first three (ok 4) lines do what I want and the last one
> will show the result. It also shows my tought processs. I have one. I
> the realize I have something else as well. Then I want to add those two
> up. And then I thing" why not show the result?

Riiiight. And since around the time we figured out that you could use
fire to cook things, what people have done is called "planning". You
look at that, you think 'okay, here's what I want, now how do I do it'.

So you take the above, and instead of writing the names, you write
a description of what they are:

"The sum of <number> and <number> is <number>"

And then you add the numbers in order:
"The sum of <number> and <number> is <number>" $NUM1 $NUM2 $TOTAL

and then, because it's printf, you spell "<number>" as "%d":
"The sum of %d and %d is %d" $NUM1 $NUM2 $TOTAL

> I rarely need formatting. I understand that in those cases printf will
> be better, but not why printf should replace echo if I am not interested
> in formatting.

Because whether or not to print a newline is formatting, and because some
versions of echo can't print some strings.

>> That's come across some. Do you usually have trouble abstracting things
>> from examples to general patterns?

> Yes. What I need is almost exactly what I am looking for and then do
> minor changes.

Then I do not think you should spend much time trying to program.
Programming is ALL abstraction.

> It is purely a hobby. If I screw up, I will be normally the only one who
> is affected. Things I have done for myself are a wallpaper changer (The
> existing ones do not work for me, due to several reasons) wallpaper
> makers, screen capture script, signature maker and stuff like that.
> So basically automating things I am too lazy to do myself all the time
> and where I can not find a program that does what I want it to do.

That can make sense. I think, though, that the most useful thing you could
do is try to study how abstraction works, so you can learn to generalize.
That skill will be amazingly useful to you in every possible aspect of your
life. Learn to do that, and you will be happier and more successful, and
you'll find programming a lot easier.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
From: Jon LaBadie on
Regarding echo vs. printf,

pk wrote:
>
> Printf has another advantage over echo: it recognizes many special escape
> sequences that echo does not recognize (or recognizes only with -e in
> certain implementations), like \n or \t.
>

Houghi, pk and I represent different sides of the problem. I've worked most
of my UNIX life in environments where echo DID recognize \n, \t, etc. So I
expect other behaviors, such as pk considers normal, as abberant.

I'd re-write pk's statement to say that as printf is consistant in recognizing
the escape sequences like \n, \t, etc. while echo is not.


If you are going to do simple literal text that does not contain escape
sequences, go ahead and use echo. For example:

echo "Hello World!"

But is that easier than:

printf "Hello World!\n"

Well I guess it is harder because you have to add the '\n' in printf. But
that is balanced by times you don't want a newline. For example suppose you
want to ask for some data to be keyed in by the operator. Further, suppose
you want the data entry on the same line as the prompt. With printf
you might do this:

printf "Enter your last name: "
read LastName

But with echo you would have to remember, does my echo suppress the default
newline by putting a '\c' at the end or by using a '-n' option? I.e. should
it be

echo "Enter your last name: \c" OR echo -n "Enter your last name: "

And what about when I copy my script to my laptop, or my next new computer.
Will its echo work the same way as this version?

I realize you are not "smart enough" to learn the intricacies of printf :)
but I find the ability to format multiple lines of simple text a great
feature. For example, suppose you are printing a list of names, first and
last. You could use a printf like this:

printf "%s %s\n" "$FirstName" "$LastName"

with output like (which is no different than you could get with echo):

George Washington
John Adams
Thomas Jefferson

But changing each %s to %12s would change the output to:

George Washington
John Adams
Thomas Jefferson

Ahh, maybe you wanted left instead of right alignment, make it %-12s:

George Washington
John Adams
Thomas Jefferson

Or the first one %12s and the second one %-12s

George Washington
John Adams
Thomas Jefferson

Lots and lots of flexibility that would be difficult to do with echo.
Yet the simple things are still simple (and more portable) with printf.

Jon