之前用ubunut大概有一个学期吧,尝试做过网站,中间遇到问题都是依靠搜索引擎,觉得还是有必要系统的学习Unix/Linux。尝试了两章Advanced Programming in the Unix Environment,感觉还是有点吃力,之前有看过《鸟叔的Linux私房菜》觉得不是我的菜。直到发现The Linux Command Line,嗯,TLCL是我的菜。
一些重要的话
Design is a function of time.
When i was a college student studying industry design, a wise professor stated that the degree of design on a project was determined by the amount of time given to the designer. If you were given five minutes to design a device “that kill flies” you design a flyswatter. If you were given five months, you might come up with a laser-guided “anti-fly” system.
Testing is an important step in every kind of software development, including scripts. There is a saying in the open source world “release early, release often.” , which reflects this fact.
Experience has show that bugs are easier to find and much less expensive to fix. If they are found early in the development cycle.
一些重要的事实
Interestingly, the line numbers reported are not where the missing quote was involved, but rather much later in the program.
It is important to verify assumptions when programming. This means a careful evaluation of the exit status of programs and commands are used by a script.
A general rule of good programming is that if a program accepts input, it must be able to deal with anything it receives.
To perform useful testing, it’s important to develop and apply good test cases. This is done by carefully input data or operating conditions that reflects edge and corner cases.
By performing the test with each of this conditions, good test coverage is achieved.
Just as with design, testing is a function of time, as well. Not every script feature needs to be extensively tested. It’s really a matter of determining what is most important.
Debugging is a fine art that can be developed through experience, both in knowing how to avoid bugs (testing constantly through development) and in finding bugs (effective use of tracing).
The shell provides a set of variables called positional parameters that contain the individual words on the command line.
You can actually access more than nine parameters using parameter expansion.
The shell also provides a variable, $#, that yields the number of arguments on the command line.
The shell provides a method, albeit a clumsy one, to do this. The shift command causes all the parameter to “move down one” each time it is executed.
Just as positional parameters are used to pass arguments to shell scripts, they can also be used to pass arguments to shell functions.
Using $* and $@ to manage the positional parameters as a group.
$@ preserves the integrity of each positional parameters.
The really powerful feature of for is the number of interesting ways we can create the list of words.
If the optional in words portion of the for command is omitted, for defaults to processing the positional parameters.
The variable used with for can be any valid variable, but i is the most common, followed by j and k.
In addition to arithmetic expansion, there is a common command line program called bc, which performs higher level math.
The shell has the ability to return the names of variables.
Parameter expansion is a good thing to know. The string manipulation expansions can be used as substitutes for other commands such as sed and cut. Expansions improve the efficiency of scripts by eliminating the use of external programs.
Bash has four parameter expansions and two options to the declare command to support upper/lowercase conversion.
Using declare, we can force a variable to always contain the desired format no matter what was assigned to it.
For most shell applications, prefixing the operator will be the most useful.
The ++ and – operators are often used in conjunction with loops.
We have seen how the shell can handle all types of integer arithmetic, but what if we need to perform higher math or even just use floating point numbers? The answer is we can’t. At least not directly with the shell.
The ability to take standard input means that we can use here documents, here strings, and pipes to pass scripts.
Arrays in bash are limited to a single dimension.
Inside the loop, we need to remove leading zeros from the hour field, since the shell will try (and ultimately fail) to interpret values “00” through “09” as octal numbers.
As bash allows arrays to contain “gaps” in the assignment of subscripts, it is sometimes useful to determine which element actually exist.
To delete an array, use the unset command.
Associative arrays use strings rather than integers as indexes.
bash allows commands to be grouped together. This can be done in one of two ways; either with a group command or with a subshell.
Where a group command or subshell really shines is with pipelines. When constructing a pipeline of commands, it is often useful to combine the several results of several commands into a single stream.
bash allows commands to be grouped together. This can be down in one of two ways: either with a group command or with a subshell. While they have a important difference, they are both used to manage direction.
Therefore in most cases, unless a script requires a subshell, group commands area preferable to subshells. Group commands are both faster and require less memory.
Process substitution allows us to treat the output of a subshell as an ordinary file for purposes of redirection. Its a form of redirection.
When we design a large, complicated script, it is important to consider what happens if the user logs off or shut down the computer while the script is running.
bash provides a mechanism for this purpose known as a trap.
Aside from the obvious step of setting proper permissions for cexposed to all users of the system, it is important to give temporary files non-predictable filenames. This avoids an exploit known as a temp race attack.
Script can be constructed to behave in a multitasking fashion. Usually this involves launching a script that, in turn, launches one or more child scripts that perform a additional task while the parent script continues to run.
In most Unix-like systems, it is possible to create a special type of file called a named pipe. Named pipes are used to create a connection between two processes and can be used just like other types of files.
for ((expression1; expression2; expression3 )); do
commands
down
(( expression1 ))
while (( expression2 )); do
commands
(( expression3 ))
done