Q:

Passing arguments to a script

I am taking the Linux Essentials class and was doing well until I hit the scripting chapter. I simply do not understand these concepts.  Wondering if someone can break the following down into ultra simplistic terms or point me to a better reference to learn it. I'm currently using netacad's curriculum.  

From the text book (with minor formatting changes):

There are some special variables in addition to the ones you set. You
  can pass arguments to your script:
#!/bin/bash
echo "Hello $1"

A dollar sign followed by a number N corresponds to the Nth argument
  passed to the script. If you call the example above with ./test.sh the
  output will be Hello Linux. The $0 variable contains the name of the
  script itself.
After a program runs, be it a binary or a script, it returns an exit
  code which is an integer between 0 and 255. You can test this through
  the $? variable to see if the previous command completed successfully.

I understand how to assign variables and how they work with the $ but the whole issue with $0 and $1 -- I just don't get it.  
Any help would be much appreciated.

A:

The description from the book is wrong (or at least missing something). To get that script to print "Hello Linux", you'd run it like this:
./test.sh Linux

If you run it with just ./test.sh, then it'll only print "Hello ", because there was no first argument and $1 is not defined. On the other hand, suppose you ran it like this:
./test.sh foo bar baz

then within the script, $0 would be "./test.sh", $1 would be "foo", $2 would be "bar", and $3 would be "baz".
As for $?, consider the following script snippet:
ls nonexistentfile.txt
echo "The exit status of ls was: $?"
echo "The exit status of echo (the first one) was: $?"

When run that'll print something like:
ls: nonexistentfile.txt: No such file or directory
The exit status of ls was: 1
The exit status of echo (the first one) was: 0

The ls command can't list nonexistentfile.txt ('cause it doesn't exist), so it prints an error message to that effect, and exits with a nonzero status to indicate that something went wrong. The first echo command prints that exit status ($?), and since it does that successfully, it exits with a status of zero. When the second echo command runs, it gets $? from the first echo command, so it prints "0".
BTW, a lot of commands just use exit statuses of 0 (success) or 1 (some sort of failure), but some use different failure statuses to indicate exactly what went wrong. Here's an excerpt from the curl manual page:
EXIT CODES
       There are a bunch of different  error  codes  and  their  corresponding
       error  messages  that  may appear during bad conditions. At the time of
       this writing, the exit codes are:

       1      Unsupported protocol. This build of curl has no support for this
              protocol.

       2      Failed to initialize.

       3      URL malformed. The syntax was not correct.

       ...

       88     FTP chunk callback reported error

       89     No connection available, the session will be queued

       90     SSL public key does not matched pinned public key

       91     Invalid SSL certificate status.

       92     Stream error in HTTP/2 framing layer.

...so a script that used curl could check $? to figure out what went wrong, and respond differently depending on the problem.

A:

$0 is the name you use to run the script. $1, $2, and so forth are the script's positional parameters, which hold the values of the command-line arguments you passed when you ran the script.
As Gordon Davisson said, the book's author must've meant to say that running ./test Linux would print Hello Linux. When you do that, ./test goes into to the special parameter 0, and Linux goes to into the first positional parameter 1. The script expands that first positional parameter by preceding it with a dollar sign ($1), just as you do with variables. If you had instead run ./test Hello Linux for Human Beings, then in the script, $1 would expand to Linux, $2 to for, $3 to Human, and $4 to Beings.
You can write a simple script to try this out:
#!/bin/bash

echo "\$0 expands to '$0'."
echo "\$1 expands to '$1'."
echo "\$2 expands to '$2'."
echo "\$3 expands to '$3'."

(Go on as far as you want. For positional parameters higher than 9, use the ${ } form of parameter expansion, e.g., expand 10 by writing ${10}. In scripts that work with many positional parameters, the special parameter @ is often used, avoiding repetition, but you can ignore that for now if you like.)
Try saving that in a file and marking the file executable, which you can do by running chmod +x simple where simple is replaced with the name of the file, if different. Then you can run it using commands like ./simple, ./simple foo, ./simple foo bar, and so on.
You'll notice that when fewer than three command-line arguments are passed, positional parameters that correspond to the ones that weren't passed expand to the empty string. That's what happens when you attempt to expand a shell parameter that is not defined. You'll notice, further, that when more command-line arguments are passed, the ones past the third are not used. That's probably what you'd expect, since the script doesn't refer to them at all.
Now try running ./simple *. The shell expands * to all the filenames in the current directory except those that start with ., so three of those will be shown as the first three positional parameters (or fewer if there aren't that many). You can try running it with other shell expansions, such as ./simple {5..10}.
You can pass command-line arguments containing blanks by enclosing them in quotes. For example, try ./simple 'foo bar' baz. Notice that $1 expands to foo bar this time, and not just to foo.
Because the shell performs various expansions, it's not always obvious how many command-line arguments you're passing to a command. An easy way to see what each argument will be is to replace the command with printf '[%s]\n'. For example:
$ printf '[%s]\n' f*
[fonts]
[fstab]
[fuse.conf]
[fwupd]

$ printf '[%s]\n' {1,3}{a..c}
[1a]
[1b]
[1c]
[3a]
[3b]
[3c]

Since you've only recently started shell scripting, the Bash reference manual may be challenging, and you might not want to read it from front to back. But I think it's a valuable resource even if you consider yourself a complete beginner. You may find the section on shell parameters useful, since it starts with what you already know--shell variables--and moves on to special parameters like ? (which people often call the $? parameter, since that's how you expand it). For general learning about Bash, especially at a more introductory level, I recommend these pages, including BashGuide.

