# Guide to Unix/Explanations/Environment
### Environment Variables

Every program inherits "environment variables" from the program that started it. This means that each program has the same environment variables as the program that started it. The environment of a program can change, in which case other programs later started by that program also have a changed environment.
The environment variable called SHELL contains the name of the default shell. (You might be running some other shell, but the default shell is always in "SHELL".) The "SHELL" environment variable is set during login and inherited by the shell. When we started the "printenv" program, it inherited the entire environment, including "SHELL", and showed "SHELL" to us.
Using printenv with no arguments gives the entire environment:
See Environment Variables to learn about specific variables.

### Process limits

Each process has limits on the following.
Limits are inherited from the parent process. The normal way to set limits is to change the limits of some shell, and then start the program from that shell. Each shell provides a different way to set limits: Bourne shell uses the ulimit command while C shell uses limit.
The following is the list of available limits, given with their C shell name ("Bourne shell option"). We need the name ("option") to show or change the limit in the C ("Bourne") shell.
Scenario: A program crashes with a message about "resource temporarily unavailable" or "too many open files".
Raise the limits in the shell from which you start the program. For example, to allow 512 open files per process:

### Shell Parameters

The shell's environment can be accessed through its parameters. There are three types of parameter:
* named parameters
* positional parameters
* special parameters
Named parameters are known as environment variables. Some of these variables are initialised when the user logs in and which the shell uses to determines its behavior. The shell also maintains certain variables throughout the login session, some of which are defined by the shell and are given special meaning, while others can be user defined.
Positional parameters enable reference to arguments supplied to shell scripts. The shell communicates process information through special parameters. Special parameters can be accessed by the user, but unlike named and positional parameters, they can only be set by the shell itself.
Environment variables are named parameters. Variables are assigned using the command line statement in the form name=value. Variable names are alphanumeric strings, they can contain numeric characters or underscores but must begin with an alphabetic character. Four examples are presented below:
Note that Unix is case sensitive, so the variable "name" is not the same as "Name". A variable can be expanded (evaluated) by preceding the variable name with a $, for example:
Variables can be concatenated:
However, there can be problem with concatenating literals with variables, using variables for the day and month but hard-coding the year gives
The problem is that the shell cannot distinguish between the variable name month and the literal value 2006. It therefore tries to expand a variable with the variable name month2006, which is not set. This can be rectified by surrounding the variables names with braces, for example:
Although the braces are not always necessary it is good practice to use them when evaluating variables.

### Quoting

Consider the following example, where the variable expansion phrase is enclosed in double quotes:
Variables enclosed in double quotes are still expanded by the shell. To prevent expansion, variables should be enclosed in single quotes. To display the string "echo $greeting" verbatim, use the statement:

### More Parameter Expansion

The shell supports quite sophisticated parameter expansion. The construct NAME-literal expands to the value of the parameter if it is set, otherwise it expands to literal value. For example:
The variable OPSYS has not been assigned a value so the result of the command is to echo the string "unix" to the screen. If the variable is assigned a value:
If the variable is set to NULL, a blank link is displayed rather than the literal value:
However, if we use name:-literal, the variable evaluates to the literal rather than its NULL value:
Using the construct name=literal the parameter is assigned the value of the literal if it has not been set. Suppose that the variable DAY has not been previously set:
then the command line below will assign the string "tuesday" to the variable DAY and echo it to screen:
The variable DAY has now been set, so if the command line is repeated with a different literal value its value remains unchanged
If DAY is assigned a NULL value, the following parameter expansion results in a NULL value being returned:
An associated expansion construct is name-value, which only returns the literal if the parameter is unassigned, it returns the assigned value even if the value is NULL.
Using the expansion construct name:=literal the parameter is assigned the value of the literal if it has not been set. For example:
Also, the literal is assigned if the parameter is NULL, the expansion is therefore:
If the parameter is set to a non-NULL value then the literal is not assigned:
The expansion construct name=value is similar to name:=value, however the literal is only assigned if the parameter was formerly unassigned. The literal is not assigned if the parameter value is NULL. Using the name:?messagestring construct, an error message can be displayed if parameter is unset or NULL:
The error message is not displayed if the parameter is assigned a non-NULL value:
Likewise, there is an associated construct name?messagestring which returns the message string only if the parameter is unset. Parameters can be expanded to substrings of their value. The expansion constructs name%pattern and name%%pattern expand to the largest and smallest substrings to the left of the pattern respectively. For example, set the variable TIME:
The command line below displays only the hour value:
whereas the following the command line display the hours and minutes
The constructs name#pattern and name##pattern expand to the largest and smallest substring to the right of the pattern respectively. So the command line below expands to the seconds:
The minutes and seconds can be extracted with:
The length of a string can be evaluated with the #name construct. For example:

### Arrays

Variables can be one-dimensional arrays and are referenced in the form name[index]. Arrays can be assigned using the name=(value1 value2 ... ) construct, so for example:
$(command) expands to the result of command on the command line. So DATE is assigned output of the command date, where each space separated string is assigned to an element in the array. So if we only want the year, then we expand the sixth element of the array:
We can change, say the time information with the assignment:
If we need to count the number or assigned array elements, then we use the expression:

### Positional Parameters

Positional parameters provide a means of accessing arguments to shell scripts. They are referenced by the numbers 1,2,3,... etc., where the numbers reflect the order in which the arguments appeared on the command line (from left to right). They cannot be assigned in the same way as named parameters, that is you cannot do this: 1=hello. Positional parameters are assigned when a shell script is invoked with command line arguments. They can, however, be assigned with the set command:
This causes the space separated strings from the output of uname -rmv to be assigned to the positional parameters. The statement below shows the values of all positional parameters that were assigned:
And this statement gives the number of assigned positional parameters (equivalent to argc in C and C++):
If we specifically want the kernel version then we expand positional parameter 1:
Double digit positional parameters need to be enclosed in braces. So if we want the architecture of the machine, we cannot do this:
The expression above is expanded to positional parameter 1 followed by a literal 0. The correct way is:
Finally, positional parameter 0 is set to the name of the current process (equivalent to argv[0], which in this case should be the name of the shell command itself:

### Special Parameters

Special parameters can be accessed by the user but can only be assigned (directly) by the shell - typically in response to some event. We have already encountered the parameters * and # which are set when a command is invoked with arguments (or the set command is used).
The ? parameter expands to the return code of the process that last exited. If we enclose a command line statement in brackets it is executed in a subshell. The command line below forks a new shell and immediately issues exit. The argument following exit is the value of the subshell’s return code (255 in this case):
The return code of the child process can be accessed by the parent by the expansion of ?. If a process terminated normally then the return code is likely to be zero. If however, the process terminated due to some error condition, it is useful if process sets a non-zero return code so that the parent can determine the reason for the termination:
The process ID of the shell is stored in $. The ps command shows that the process ID of my shell is 10005, which is what is given by the expansion of $:
The ! parameter evaluates to the process ID of the last background process. To demonstrate, the statement below invokes the sleep command (which sleeps for 60 seconds) in the background:
The process ID of the background process is displayed on the screen (in this case 24835). Expansion of the ! parameter confirms this:

### Exporting Parameters

Processes do not inherit environment variables from their parent unless the variables are exported. The command line below displays the process ID of the current process followed by the value of greeting (which was assigned earlier):
If we start a new shell and issue the command again we see that greeting is not set in the child process:
Terminate the current shell process and return to the parent, then export greeting:
You can confirm that a variable has the export attribute set by typing:
Now start a new shell again and evaluate greeting:
The new shell has inherited the variable greeting and can evaluate it. A variable retains its export attribute (until the shell is terminated) even if it is reassigned, but it can be removed using the typeset command:
In Bash (and Kornshell, but not Bourne shell), a variable can be assigned and exported in one command line statement:
This page or section of Guide to Unix is a stub. You can help by expanding it.