Introduction
People who work with shell are familiar with shell programming in Unix/Linux. # is mentioned in all shell programming books #! /Bin/bash. What exactly does it contain? What does this string mean for the operating system? You may say, isn't it true that the/bin/bash program will be used to explain the script program? Of course you are right. Let's look at our title. Here we will talk about the interpreter. Let's take a look at what the first sentence in the script file actually means to the system. But one thing we can clarify first is that the so-called interpreter refers #! The executable program after the row.
1. Let's talk about exec functions.
If you never write a C program, you may need to read the content in this section more carefully and test it.
Code:
# Include
Extern char ** environ;
Int execl (const char * path, const char * Arg ,...);
Int execlp (const char * file, const char * Arg ,...);
Int execle (const char * path, const char * Arg,..., char * const envp []);
Int execv (const char * path, char * const argv []);
Int execvp (const char * file, char * const argv []);
A total of five exec functions are listed in the preceding table. They are used in the same way: execute a new code. The difference is that the parameters passed to the function are different. Here I will talk about the execl function: the first parameter path is to point to the path where the execution bit file is set, the variable parameter list points to the parameter list passed to the execution file (including the parameter 0, that is, the name of the execution file ). The last parameter is (char *) 0, indicating that the parameter list ends.
For the interpreter, the exec family function does this (execl is used as an example). If path points to a script, the first line of the script is #! In this way:
To #! The following string is the command followed by the parameter list specified in the execl parameter list, forming a new program execution.
The following is an example to verify the result:
The function of the C program below is to return all command line parameters.
Code:
/* Program Source: showargs. C *
* Program name: showargs */
# Include
Int
Main (INT argc, char * argv [])
{
Int I;
For (I = 0; I <argc; I ++)
{
Printf ("Arg [% d]: % s/n", I, argv [I]);
}
Return 0;
}
Compile: gcc-O showargs. c
Run:
Code:
$ Pwd
/Home/Kiron
$./Showargs arg1 arg2
Arg [0]:./showargs
Arg [1]: arg1
Arg [2]: arg2
We can write another script in the same directory:
Code:
#! /Home/Kiron/showargs addargs
I have not typed an error. Yes, this script has only one line. This script is named testexec. After the execution bit is added, the execution is as follows:
Code:
$./Testexec
Arg [0]:/home/Kiron/showargs
Arg [1]: addargs
Arg [2]:./testexec
Why? I guess someone doesn't understand the 2nd parameters./testexec. Now I want to sell a token and then introduce a C program:
Code:
/* Program Source: mytest. C *
* Program name: mytest */
# Include
Int
Main (void)
{
Execl ("/home/Kiron/testexec", "testexec", "arg1", "arg2", (char *) 0 );
Return 0;
}
Compile: gcc-O mytest. c
Run:
Code:
$./Mytest
Arg [0]:/home/Kiron/showargs
Arg [1]: addargs
Arg [2]:/home/Kiron/testexec
Arg [3]: arg1
Arg [4]: arg2
Taking a closer look at the three examples above, the answer begins to pop up. As mentioned at the beginning, the exec family functions are processed #! The following string is the command followed by the parameter list specified in the execl parameter list, forming a new program execution. Analyze the mytest. C source program. execl executes the command result in this way. The content of/home/Kiron/testexec is #! /Home/Kiron/showargs addargs, then #! The following string "/home/Kiron/showargs addargs" is added with the command parameter list: "/home/Kiron/testexec arg1 arg2" to form a new program line: /home/Kiron/showargs addargs/home/Kiron/testexec arg1 arg2. For the testexec script, when we call it in shell, shell calls fork, exec, wait to execute it, that is, it is executed with the program mytest. c uses the exec function. First, the exec function pair #! The interpreter of this script is/home/Kiron/showargs. Then, the command line is processed as "/home/Kiron/showargs addargs./testexec ".
Note :#! The path of the interpreter in the row must be a full path, and the exec function does not handle it specially. For example, you can use the PATH variable to search for its actual path. Therefore, the path is correct by the programmer.
2. The first sentence of my script must be #! /Bin/bash?
Of course it's not necessary. Through the above explanation, the first sentence is actually #! It is the path of the interpreter program for the script. The content of the script is explained by the interpreter. We can use various interpreters to write the corresponding script, such as the/bin/CSH script, /bin/perl script,/bin/awk script,/bin/SED script, and even/bin/ECHO. Can we write a/bin/ECHO script file? Let's try it. The following is an example:
Code:
#! /Bin/ECHO-e
I named the program with only one line (in fact, it can only be one line, and the Echo program is not a programming language designed to be like awk and can be written as a source program file) as myecho, add the permission and execute it:
Code:
$./Myecho "Hi/"
./Myecho hi
If your echo supports the-E Option and your work environment is still quiet, you should also hear the crisp terminal ring when you get the above results. But such a program is useless.
3. What can I do with the interpreter?
However, the above echo script does not have any function in actual application. We can come up with a small experiment result. Not all executable binary files can be used to write the interpreter script. So what is the use of the interpreter script? If you have a programmable interpreter, you may be able to write the interpreter program to simplify your work. For example, commonly used interpreters such as awk, Perl, and bash. However, unfortunately, not all programmable programs are useful interpreters, and the interpreter for the script can be obtained from the first line during the exec script, then use exec to explain the script (it may be an option to control it, for example #! /Bin/awk-F), also including the form such #! The first line of/path/. If the interpreter cannot ignore this line, an error will occur, in addition, the interpreter must be able to explain the remaining Program Statements (this sentence seems nonsense, but imagine that the above myecho program adds some "Hello World" lines, will it be valid? The same is true for S/Unix/P in the mysed program below ). For example, a program such as awk, Perl, and bash can process the line starting with # as a comment line to write a useful script.
Let's look at the following mysed program,
Code:
#! /Bin/sed-F
S/Unix/P
An error occurred while executing./mysed. It is interpreted as "/bin/sed-f. /mysed ", where the-F option indicates that the content in the file is used as the SED command input, but the SED command input cannot be "#! /Bin/sed-F "explanation, then the program fails.
Therefore, a useful interpreter should be a program similar to bash, Perl, and awk, and be able to explain some of the specified statements. The following is a script program named myawk that calculates the number of file lines and the number of words written by the awk program.
Code:
#! /Usr/bin/awk-F
Begin {
Sum = 0;
}
{Sum + = NF ;}
End {
Printf ("file/" % S/"have % d line, % d Words./N", filename, NR, sum );
}
After setting the execution bit, run the following command:
Code:
$ Echo-e "Hi/nhello world"> test.txt
$./Myawk test.txt
File "test.txt" have 2 line, 3 words
Run here. /myawk is executed as "/usr/bin/awk-f. /myawk test.txt ", because the line starting with # In the awk command is considered as a comment line and ignored, awk ignores the first line "#! /Usr/bin/awk-F ". The correct line starting with non-# is used as the input mode and command and can be interpreted. Therefore, this program is correct, it can be executed smoothly.