Site Network: Home | About

One of the good collections that I could able to gather is abt the evaluation of Shell command. Most of this extraction is directly from Classic Shell Scriptin-Oreilly. It's just like a tutorial, pls bear with me, I don't have much time to elaborate it. I think this is good enough. Though it is a fundamental concept, I don't prefer someone who is new to shell env to read this post. Unnecessarily it will create chaos. Ok....let us start.... Each line that the shell reads from the standard input or a script is called a pipeline; it contains one or more commands separated by zero or more pipe characters (). (Actually, several special symbols separate individual commands: semicolon, ;, pipe, , ampersand, &, logical AND, &&, and logical OR, .) For each pipeline it reads, the shell breaks it up into commands, sets up the I/O for the pipeline, and then does the following for each command, in the order shown: 1) Splits the command into tokens that are separated by the fixed set of metacharacters: space, tab, newline, ;, (, ), <, >, , and &. Types of tokens include words, keywords, I/O redirectors, and semicolons. It's a subtle point, but variable, command, and arithmetic substitution can be performed while the shell is doing token recognition. 2) Checks the first token of each command to see if it is a keyword with no quotes or backslashes. If it's an opening keyword (if and other control-structure openers, {, or (), then the command is actually a compound command. The shell sets things up internally for the compound command, reads the next command, and starts the process again. If the keyword isn't a compound command opener (e.g., is a control-structure middle like then, else, or do, an end like fi or done, or a logical operator), the shell signals a syntax error. 3) Checks the first word of each command against the list of aliases. If a match is found, it substitutes the alias's definition and goes back to step 1; otherwise it goes on to step 4. The return to step 1 allows aliases for keywords to be defined: e.g., alias aslongas=while or alias procedure=function. Note that the shell does not do recursive alias expansion: instead, it recognizes when an alias expands to the same command, and stops the potential recursion. Alias expansion can be inhibited by quoting any part of the word to be protected. 4) Substitutes the user's home directory ($HOME) for the tilde character (~) if it is at the beginning of a word. Substitutes user's home directory for ~user. Tilde substitution (in shells that support it) occurs at the following places:

  • As the first unquoted character of a word on the command line
  • After the = in a variable assignment and after any : in the value of a variable assignment
  • For the word part of variable substitutions of the form ${variable op word}

5) Performs parameter (variable) substitution for any expression that starts with a dollar sign ($).

6) Does command substitution for any expression of the form $(string) or `string`. 7) Evaluates arithmetic expressions of the form $((string)). 8) Takes the parts of the line that resulted from parameter, command, and arithmetic substitution and splits them into words again. This time it uses the characters in $IFS as delimiters instead of the set of metacharacters in step 1. Normally, successive multiple input occurrences of characters in IFS act as a single delimiter, which is what you would expect. This is true only for whitespace characters, such as space and tab. For nonwhitespace characters, this is not true. For example, when reading the colon-separated fields of /etc/passwd, two successive colons delimit an empty field: while IFS=: read name passwd uid gid fullname homedir shell do ... done < /etc/passwd

9) Performs filename generation, a.k.a. wildcard expansion, for any occurrences of *, ?, and [...] pairs.
10) Uses the first word as a command following the search orderi.e., as a special built-in command, then as a function, then as a regular built-in command, and finally as the first file found in a search of $PATH.
11) Runs the command after setting up I/O redirection and other such things. On the flip side is the eval command, which lets you go through the process again. Performing command-line processing twice may seem strange, but it's actually quite powerful: it lets you write scripts that create command strings on the fly and then pass them to the shell for execution. This means that you can give scripts intelligence to modify their own behavior as they are running. The total sequence of steps is pretty complicated. Each step happens inside the shell's memory as command lines are processed; it's not really possible to get the shell to show you each step as it happens. However, we can pretend to peek inside the shell's memory and see how the command line is transformed at each phase. We start with the following:
$ mkdir /tmp/x Create temporary directory
$ cd /tmp/x Change there
$ touch f1 f2 Create files for wildcarding
$ f=f y="a b" Assign two variables
$ echo ~+/${f}[12] $y $(echo cmd subst) $((3 + 2)) > out A busy command Evaluation proceeds in the steps outlined previously: 1) The command is first split into tokens based on the shell's syntax. Most importantly, the I/O redirection > out is recognized and saved for later. Processing continues with this line, where the extent of each token is as shown on the line below the command:
echo ~+/${f}[12] $y $(echo cmd subst) $((3 + 2))
--1-- ------2------ -3- ----------4---------- -----5------ 2) The first word (echo) is checked to see if it's a keyword, such as if or for. In this case it's not, so processing continues with the line unchanged.
3) The first word (still echo) is checked to see if it's an alias. It isn't, so processing continues with the line still unchanged.
4) All words are scanned for tilde expansion. In this case, ~+ is a ksh93 and bash extension which is equivalent to $PWD, the name of the current directory.Token 2 is modified, and processing continues with this:
echo /tmp/x/${f}[12] $y $(echo cmd subst) $((3 + 2)) --1-- -------2-------- -3- --------4--------- ----5---- 5) The next step is variable expansion: tokens 2 and 3 are modified. This produces:
echo /tmp/x/f[12] a b $(echo cmd subst) $((3 + 2)) --1-- ------2------ -3- --------4--------- ----5----- 6) Command substitutions are processed next. Note that this can recursively invoke all the steps in the list! In this case, since we're trying to keep things easy to follow, command substitution modifies token 4, producing:
echo /tmp/x/f[12] a b cmd subst $((3 + 2))
--1-- ------2------ -3- -----4---- ----5-----
7) Arithmetic substitution is now performed. Token 5 is modified, and the result is:
echo /tmp/x/f[12] a b cmd subst 5 --1-- ------2------ -3- ----4---- -5-
8) The results of all the previous expansions are rescanned for the characters in $IFS. If found, they act as separators, creating additional words. For example, the two characters $y made up one word originally, but the expansion a-space-b is split at this stage into two words, a and b. The same applies for the results of the command substitution, $(echo cmd subst). The previous token 3 becomes tokens 3 and 4, and the previous token 4 becomes tokens 5 and 6. The result is:
echo /tmp/x/f[12] a b cmd subst 5 --1-- ------2------ 3 4 ----5----- 6
9) The last substitution stage is wildcard expansion. Token 2 becomes tokens 2 and 3. The result is:
echo /tmp/x/f1 /tmp/x/f2 a b cmd subst 5 --1-- ----2----- -----3----- 4 5 --6- --7-- 8
The shell is now ready to run the final command. It looks up echo. The shell actually runs the command. It first performs the > out I/O redirection, and then calls its internal version of echo to print out the final arguments.
Here is the final result:
$ cat out /tmp/x/f1 /tmp/x/f2 a b cmd subst 5
----------------------------------
Hope you have enjoyed it, few might have got confused. I will try to update this post as soon as I get better info.(especially on Eval command).
This post in brief....
Split into Tokens -> find keywords -> replace aliases -> tilde expansion -> Variable substittuion -> Command substittuion -> Arithmetic substittuion -> split into tokens again using $IFS values-> wild card expansion-> execute final command
- Karteek :)

0 Comments:

Post a Comment