Bash command line processing [detailed]
I have a major reason why many brothers write scripts or commands, because I don't know the command line processing of BASH. I have summed it here, you can refer to it. It also involves double quotation marks, single quotes, and EVAL skills, I will tell them one by one.
Code:
----------- single quotes
| - -------------------------> | | ------------------- ----- |
| -----------------------> | 1. Separate into a marker | ---- -------------- - | | | |
| | -------------------> | | Double Quotes | |
| | | ------------- |
| | | | || | |
| | | Read the next command // | | |
| | | ------------------------------------------- |
| | | | | 2. | | | |
| | ------ | Check the first mark | | | |
| | | Open keywords other keywords | | | |
| | | | Non-Keywords | | | |
| | ------------------------------------------- |
| | | || | |
| | / / | |
| | ----------------------------- |
| | Extend alias | 3. Check the first mark | | | | |
| | ------------ | Alias | | |
| | Not alias | | | | |
| ----------------------------- |
| | || | |
| // | |
| -------------- | |
| | 4. Calbum extension | | || -------------- |
| | || | |
| // | |
| -------------- | |
| | 5. ~ Symbol extension | | | | |
| -------------- | |
| | || | |
| // | |
| ------------ Double Quotes | |
| | 6. Parameter extension | <----------------- | |
| -------------- |
| | || |
| // |
| ------------------------------ |
| | 7. Command Replacement (Nested command line processing) | |
| ------------------------------ |
| | || |
| // |
| -------------- Double Quotes |
| | 8. Argumentation | ------------------ | |
| -------------- | |
| | || | |
| // | |
| -------------- | || | 9. Word segmentation | | | |
| -------------- | |
| | || | |
| // | |
| -------------- | |
| | 10. Path name extension | | | | |
| -------------- | |
| | || | |
| // | |
| ---------------------------------------- |
| | 11. Commands: Functions, Built-in Commands, Executable Files | <--- | ----- |
| ----------------------------------------
| ||
| //
| Bring the parameters into the next command -------------
| ---------- EVAL -------------- | 12. Run command |
------------
The Shell is called a pipe row from each line read from the standard input or script that contains one or more commands separated by 0 or more pipe characters (|). For each pipeline, 12 steps are performed.
In combination with the above illustration, 12 steps of the command line are given.
1.
Divide the command line into a sign separated by a fixed element character:
Space, Tab, Newline,;, (,), <,>, |
The marker type includes words, keywords, I / O registration characters and semicolons.
2.
Detect the first mark of each command to see if it is a keyword without quotation marks or reverse slope. If it is an open keyword, such as if and other control structures start strings, function, {, or (, the command is actually a composite command. SHELL is handled internally, reading the next command, and Repeat this process. If the keyword is not a composite command start string (such as the keyword in the middle of the Control Structure), a syntax error signal is given.
3.
Check the first keyword for each command based on the alias list. If you find a corresponding match, replace its alias definition and return the first step; otherwise enter step 4. This policy allows recursive alias and allows you to define keyword alias. Alias Procedure = FUNCTION
4.
Perform braces extension, such as A {B, C} becomes AB AC
5.
If ~ is at the beginning of the word, replace it with $ home ~. Replace ~ USER using USR's home directory.
6.
Replace the parameter (variable) replacement for any expression of the symbol $
7.
Command replacement of forms $ (string)
Here is the nesting command line processing.
8.
Calculate the arithmetic expression of $ (string)
9.
The parameters, commands, and arithmetic replacement parts of the line are divided into words, which uses the characters in $ IFS to make splitters rather than the meta character set of step 1.
10.
For the appearance *,?, [/] To execute the path name extension, also known as wildcard expansion
11.
Mandarin to check by command priority table (skip alias)
12.
Set the I / O redirection and other operations to execute the command.
About reference
1. Single quotes skip the top 10 steps, can't put single quotes in single quotes
2. Double quotes skip steps 1 to 5, steps 9 ~ 10, that is, only 6 to 8 steps are processed.
That is, the dual quotation ignores the pipe character, alias, ~ replace, wildcard extension, and split by separator into words.
The single quotes in the double quotation have no effect, but the dual quotation allows parameters to replace, command replacement, and arithmetic expressions. You can include double quotes in the dual quotation marks, and the mode is plus an escaper "/" must also escape $, `, /.
eVal
The role of EVAL is to perform the command line processing again, that is, for a command line, perform two command line processing.
This order is good, it will cost a certain effort. I will give two examples and throw bricks.
Example 1:
Implement the control structure for the shell with EVAL tips.
Code:
[root @ Home root] # cat myscript1
#! / bin / sh
Evalit () {
IF [$ cnt = 1]; then
Eval $ @
Return
Else
Let CNT = CNT-1
Evalit $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
Fi
Eval $ @
}
CNT = $ 1
Echo $ CNT | EGREP "^ [1-9] [0-9] * $"> / dev / null
IF [$? -eq 0]; then
Shift
Evalit $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
Else
Echo 'Error !!! Check Your Input!'
Fi
[root @ Home root] # ./myscript1 3 hostname
HOME
HOME
HOME
[root @ Home root] # ./myscript1 5 id | cut -f1 -d ''
UID = 0 (root)
UID = 0 (root)
UID = 0 (root)
UID = 0 (root)
UID = 0 (root)
Note that there are two very special variables in Bash, which saves the parameter list.
$ *, Saved the string group divided by the split specified by $ IFS.
$ @, Saved the parameter list, which is "$ 1" "$ 2" ...
Here I used the function recursive and EVAL implemented the FOR structure.
When executing Eval $ @, it experienced steps as follows:
Step 1, divide into Eval $ @
Step 6, expand $ @ htName
Step 11, find the built-in command evAl
Repeat the command line processing, step 11, find the hostname command, execute.
Note: Maybe someone wants to think, why is it necessary to use EVAL? Direct $ @ to execute a command. error! Here is a typical example of everyone to see.
Code:
[root @ Home root] # a = "id | cut -f1 -d ''"
[root @ Home root] # $ a
ID: Invalid Options - F
Try executing 'ID --help' to get more information.
[root @ Home root] # Eval $ a
UID = 0 (root)
If the command line is complex (including pipes or other characters), the content directly executes the $ A string will be wrong. analyse as below.
The processing of $ A is on the 6th step - parameter extension, that is, skipping the pipeline analysis, and "|", "cut", "-f1", "-d" has become the parameter of the ID command, Of course, it will be wrong.
However, use EVAL, which processes the "ID", "|", "CUT", "-f1", "-d", "-f1", "-d", which can be processed again, this time it can be correct. Analyze the pipeline.
All in all, to ensure that your command or script design can correctly process the command line, skip any steps, can cause unexpected errors!
Example 2:
Set the LS color display of the system
Code:
Eval $ (Dircolors -B / etc / Dircolors)
Eval statement notifies the shell to accept the evAl parameter and run them again through all the steps processed by the command line.
It allows you to write scripts to create a command string free, and pass them to the shell;
$ () Is the command replacement, returns the output string of the command.
Where the DIRCOLORS command generates the Bash code for setting the environment variable LS_COLORS according to the / etc / dircolors profile, the content is as follows
Code:
[root @ localhost root] # DIRCOLORS -B> TMP
[root @ localhost root] # cat tmp
LS_COLORS = 'NO = 00: FI = 00: Di = 01; 34: ln = 01; ......
Export ls_colors
# Here I don't specify a configuration file, so DIRCOLORS generates code according to the preset database.
Its output is passed to the shell execution by the eval command.
Eval is a flexible application for the Bash Shell command line processing rule, and thus constructing a "intelligent" command to implement complex features.
The command mentioned above is a very ordinary application of EVAL, which repeats the command line parameter transfer process, and executes commands of commands.
In fact, it is a difficult point of Bash, which is a high-level Bash programmer's compulsory skill.
Command priority table
1. Alias 2. Keyword 3. Function 4. Built-in command 5. Script or executable ($ PATH)
In view of the confusion that will encounter in some learning, I will give some interesting orders.
Command Builtin Enable
The above command line is mentioned, the 11th step will be commanded, how about it?
Its default lookup order is functions, internal commands, scripts, and executable code. We tend to skip some findings in actual programming to meet certain functional needs. At this time, you should use these three commands to show magic ~~
Command
Skating the alias and functions, in other words, it only looks for internal commands and the scripts found in the search path or executable.
Here is an interesting example.
Code:
[root @ Home root] # type -all pwd
PWD IS A shell builtinpwd is / bin / pwd
[root @ Home root] # cat myscript2
#! / bin / sh
PWD () {
Echo "this is the current directory."
Command PWD
}
PWD
[root @ Home root] # ./myscript2
This is the capital Directory.
/ root
I use the PWD () function to replace the built-in command PWD and external command / bin / pwd, then execute the built-in command PWD in the script. Here we use Command? It is to avoid the function falling into the recursive loop because the function name is the same name with the built-in command, and the priority of the function is high than the built-in command.
BUILTIN
As the name suggests, it only looks for the built-in command. This order is very simple, not to say.
enable
In contrast to Builtin, it shields a built-in command, allows you to run a shell script or an executable code of the same name without a full path name.
For example.
There are two PWD commands, one is the shell built-in, one is an executable program.
After performing some strange path names, the built-in PWD will print "error message", but the external PWD will print "original face" in the current directory. please look below:
Code:
[root @ Home root] # CD //
[root @ Home //] # PWD
//
[root @ Home //] # type -all pwd
PWD is a shell builtin
PWD IS / BIN / PWD
[root @ home //] # / bin / pwd
/
[root @ Home //] # enable -n PWD
[root @ Home //] # PWD
/
Thus, after blocking the built-in PWD command with Enable -n, you can print the correct path name with the external PWD.