How do I find information on bash special parameters ($* $# $# $? $- $$ $! $0 $_)? [duplicate] - bash

This question already has answers here:
What are the special dollar sign shell variables?
(4 answers)
Closed 5 years ago.
(I've seen a number of questions here about Bash special parameters. It can be difficult to search for things like $*, both in the Bash manual and via Google. This question is intended to be a general reference for these questions.)
The Bash shell defines a number of "special parameters" (which is itself a bit confusing, since most of us think of them as "variables", not "parameters"). References to them consist of a dollar sign followed by some punctuation character.
Google searches for strings consisting of punctuation characters are notoriously difficult, and there are no occurrences of, for example, $? in the Bash Reference Manual.
How can I find information on particular Bash special parameters?

Documentation on Bash special parameters:
$* $# $# $? $- $$ $! $0 $_
can be found in the Bash Reference Manual, specifically in section 3.4.2, "Special Parameters". If you have the bash documentation installed on your system, you can type
% info bash
and then search for "Special Parameters".
As rici points out in a comment, within the info command you can also find the special parameters via the index: type i and then type the single character (excluding the $), then Enter. This doesn't work for ?, and searching for ! finds a different section first (typing , to find the next entry works). (This still works reasonably well after I apply my patch.)
It's unfortunate, IMHO, that this section refers to these parameters without the leading $ character. (I've just submitted a patch that changes this.)
A brief summary (but read the manual for details):
$*: Expands to the positional parameters starting with $1.
$#: Also expands to the positional parameters, but behaves differently when enclosed in double quotes.
$#: Expands to the number of positional parameters in decimal.
$?: Expands to the exit status of the most recent command. (Similar to $status in csh and tcsh.)
$-: Expands to the current option flags.
$!: Expands to the process ID of the most recent background command.
$0: Expands to the name of the shell or script. (Note that $0, unlike $1 et al, is not a positional parameter.)
$_: Initially set to the absolute pathname use to invoke the shell or shell script, later set to the last argument of the previous command. (There's more; see the manual.)
UPDATE :
As of bash version 4.3, released 2014-02-26, the bash documentation is annotated to show the full names of these variables. In release 4.2:
`#'
Expands to the number of positional parameters in decimal.
In release 4.3:
`#'
($#) Expands to the number of positional parameters in decimal.

Related

Where is "key=value bash-script" usage documented?

I often see key=value bash-script to pass variables to a bash script. Here is an example:
$ echo $0
-bash
$ cat foo.sh
#!/usr/bin/env bash
echo "key1: $key1"
$ key1=value1 ./foo.sh
key1: value1
I have checked Bash Reference Manual. But I can't a description related to this usage.
Section 3.7.4 "Environment"
The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments, as described in Shell Parameters. These assignment statements affect only the environment seen by that command.
Apparently the online version of the documentation fails to describe the syntax of a simple command completely. It reads:
3.2.1 Simple Commands
A simple command is the kind of command encountered most often. It’s just a sequence of words separated by blanks, terminated by one of the shell’s control operators (see Definitions). The first word generally specifies a command to be executed, with the rest of the words being that command’s arguments.
There is some information about the variable assignments that may precede a simple command on the section Simple Commands Expansion:
3.7.1 Simple Command Expansion
When a simple command is executed, the shell performs the following expansions, assignments, and redirections, from left to right.
The words that the parser has marked as variable assignments (those preceding the command name) and redirections are saved for later processing.
...
The text after the = in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable.
The manual page bundled with the shell seems to be better at this. It says (the emphasis is mine):
Simple Commands
A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections, and terminated by a control operator.
You can always read the documentation of bash (and of any other CLI program installed on your computer) using man.
Type man bash on your terminal and use the usual keys (<spacebar>, b, /, q etc.) to navigate in the document. Behind the scenes, man uses your default pager program (which is, most probably, less) to put the information on screen.

What are the special dollar sign variables in zsh?

When using bash, there are self-referential variables that don't seem to be available in zsh. For example, $? gets the exit status of the most recent foreground process, $_ gets the last parameter of the previous command, etc.
Are there equivalents to these in zsh? I ask with reference to this question for bash.
bash calls these the special parameters (to distinguish them from ordinary variables and the positional parameters). zsh implements essentially the same set, but documents them along with other parameters set by the shell, though it does also tag each one as special.
See man zshparam:
PARAMETERS SET BY THE SHELL
In the parameter lists that follow, the mark `<S>' indicates that the
parameter is special. `<Z>' indicates that the parameter does not
exist when the shell initializes in sh or ksh emulation mode.
The following parameters are automatically set by the shell:
! <S> The process ID of the last command started in the background
with &, or put into the background with the bg builtin.
# <S> The number of positional parameters in decimal. Note that some
confusion may occur with the syntax $#param which substitutes
the length of param. Use ${#} to resolve ambiguities. In par-
ticular, the sequence `$#-...' in an arithmetic expression is
interpreted as the length of the parameter -, q.v.
ARGC <S> <Z>
Same as #.
$ <S> The process ID of this shell. Note that this indicates the
original shell started by invoking zsh; all processes forked
from the shells without executing a new program, such as sub-
shells started by (...), substitute the same value.
[... etc ...]

Bash tilde not expanding in certain arguments, such as --home_dir=~

Bash is not expanding the ~ character in the argument --home_dir=~. For example:
$ echo --home_dir=~
--home_dir=~
Bash does expand ~ when I leave out the hyphens:
$ echo home_dir=~
home_dir=/home/reedwm
Why does Bash have this behavior? This is irritating, as paths with ~ are not expanded when I specify that path as an argument to a command.
bash is somewhat mistakenly treating home_dir=~ as an assignment. As such, the ~ is eligible for expansion:
Each variable assignment is checked for unquoted tilde-prefixes immediately following a : or the first =. In these cases, tilde expansion is
also performed.
Since --home_dir is not a valid identifier, that string is not mistaken for an assignment.
Arguably, you have uncovered a bug in bash. (I say arguably, because if you use set -k, then home_dir=~ is an assignment, even though it is after, not before, the command name.)
However, when in doubt, quote a string that is meant to be treated literally whether or not it is subject to any sort of shell processing.
echo '--home_dir=~'
Update: This is intentional, according to the maintainer, to allow assignment-like argument for commands like make to take advantage of tilde-expansion. (And commands like export, which for some reason I was thinking were special because they are builtins, but tilde expansion would have to occur before the actual command is necessarily known.)
Like chepner says in their answer, according to the documentation, it shouldn't expand it even in echo home_dir=~. But for some reason it does expand it in any word that even looks like an assignment, and has done so at least as far back as in 3.2.
Most other shells also don't expand the tilde except in cases where it really is at the start of the word, so depending on it working might not be such a good idea.
Use "$HOME" instead if you want it to expand, and "~" if you want a literal tilde. E.g.
$ echo "~" --foo="$HOME"
~ --foo=/home/itvirta
(The more complex cases are harder to do manually, but most of the time it's the running user's own home directory one wants.)
Well, that's because in echo --home_dir=~, the '~' does not begin the word and the output of echo is not considered a variable assignment. Specifically, man bash "Tilde Expansion" provides expansion if
If a word begins with an unquoted tilde character (~); or
variable assignment is checked for unquoted tilde-prefixes immediately following a : or the first =.
You case doesn't qualify as either.

! in a string makes it unusable in a command line - error message "event not found" [duplicate]

This question already has answers here:
echo "#!" fails -- "event not found"
(5 answers)
Closed 7 years ago.
This is a quite simple question that I can't find an answer to.
I have a string such as "ASDGFasd#!dasd" which I would like to enter into the command line as an argument e.g.
python test.py "ASDGFasd#!dasd"
This does not run test.py with the string provided (as I want it to), but instead returns:
bash: !dasd: event not found
How do solve this?
I am using ubuntu 14.04 LTS with python 2.7
I'll attempt a summary of existing answers to similar questions:
! is expanded by bash as part of the history expansion feature, which is by default on in interactive shells, but off by default in scripts (non-interactive shells).
Specifically, ! together with the following characters is interpreted as an expression that recalls a previous command; e.g., !! recalls the most recently executed command, and !l recalls the most recently executed command starting with l.
An easy way to avoid expansion of ! altogether is to turn history expansion off, which is advisable, given that the feature can be disruptive and given that the readline library's features, which were introduced later, are a superior replacement.
To turn history expansion off, add set +H (or set +o histexpand) to your ~/.bashrc file (or ~/.bash_profile file on OS X) - this is recommended in the highest-voted answer to "-bash: !": event not found"
An alternative, though probably ill-advised, is to choose an alternative character for history expansion, by setting the special histchars shell variable to the desired character.
With history expansion ON, ! is expanded:
always:
in unquoted strings: echo hi!
in double-quoted strings, irrespective of embedded command substitutions: echo "hi!"
Note that this means that ! is even expanded inside a single-quoted string inside a command substitution embedded in a double-quoted string: apparently, history expansion occurs very early during parsing, before the internals of the double-quoted strings are parsed to recognize embedded command substitutions; e.g.:
echo "$(echo 'hi!')" # '!' is still expanded(!) - this is the gist of question "How to escape history expansion exclamation mark ! inside a double quoted " command substitution like "$(echo '!b')"?"
Strictly speaking, ! parsing doesn't even respect double-quotes per se, and considers any run of non-whitespace characters following ! the history-expansion argument, including "; for instance, echo foo!" - despite imbalanced double-quotes - is considered a valid command, as is echo foo!bar"baz.
never:
in single-quoted strings: echo 'hi!'

Code explanation required for a kornshell scripting novice

I know java so the do while and case are no issue. I have read the man page for getopts. It has been of some use. Really im looking for plain english explanation of what is happening with "getopts :d:p:nil optname"
while getopts :d:p:nil optname
do
case $optname in
The shell script is invoked with a collection of arguments, like any other command on Unix.
The getopts built-in command helps parse those arguments, dividing them up into:
Flags with no value associated with them
Flags with a value associated with them
Non-flag arguments (usually but not necessarily file names)
Given the loop:
while getopts :d:p:nil optname
the flags with no value associated with them are -n, -i and -l. The flags which need a value are -d and -p. The loop
processes each of the flag arguments in the command line in turn. The single letter for the option is stored in the shell variable $optname. If the flag takes a value, then that is in $OPTARG.
The leading colon to the string defining the options says that getopts should not report errors, leaving that up to the script.
The getopts command returns success (0) when there was an option found; it returns failure (non-zero, probably 1) when there are no more options to process.
This can be because it came across an argument that didn't start with a dash, or because it came across the special marker argument --.
See also the getopt() function in C programming. The facilities of the shell are based on that.
There are extensions of various sorts to handle multi-letter option names. See also Using getopts in bash shell script to get long and short command line options.
There should be some useful information in help getopts:
getopts: getopts optstring name [arg]
Parse option arguments.
Getopts is used by shell procedures to parse positional parameters
as options.
OPTSTRING contains the option letters to be recognized; if a letter
is followed by a colon, the option is expected to have an argument,
which should be separated from it by white space.
Each time it is invoked, getopts will place the next option in the
shell variable $name, initializing name if it does not exist, and
the index of the next argument to be processed into the shell
variable OPTIND. OPTIND is initialized to 1 each time the shell or
a shell script is invoked. When an option requires an argument,
getopts places that argument into the shell variable OPTARG.
...
Here OPTSTRING is the sequence :d:p:nil and name is called optname. The case statement will match against each different option while they are placed in optstring.

Resources