In this chapter we are going to look at some of the "magic" that occurs on the command line when you press the enter key.While we will examine several interesting and complex features of the shell,we will do it with just one new command:
- echo - Display a line of text
(character)expand
Each time you type a command line and press the enter key,bash performs several processes upon(根据) the text before it carries out your command.We have seen a couple of cases of how a simple character sequence,for example "*",can have a lot of meaning of to the shell.(我们已经见过几个例子:例如一个简单的字符序列“*”,对shell来説有着多么丰富的涵义)The process that makes this happen is called expansion.With expansion,you type something and it is expanded into something else before the shell acts upon it.To demonstrate(说明,演示,证明) what we mean by this,let's take a look at the echo command.echo is a shell builtin that performs a very simple task.It prints out its text arguments on standard output:
That's pretty straightforward(正直的,坦率的,老实的,简单的,易懂的).Any argument passed to echo gets displayed.Let's try another example:
So what just happened?Why didn't echo print"*"?As you recall(召回,回想) from our work with wildcards, the "*" character means match any characters in a filename,but what we didn't see in our origianal discussion was how the shell does that.The simple answer is that the shell expands the "*" into something else(in this instance,the names of the files in the current working directory) before the echo command is executed.When the enter key is pressed,the shell automatically expands any qualifying(使具有资格的,符合条件的) characters on the command line before the command is carried out,so the echo command never saw the "*",only its expanded result.Knowing this ,we can see that echo behaved as expected.
Pathname expansion
The mechanism(构造,机制) by which wildcards work is called pathname expansion.(通配符所依赖的工作机制叫路径名展开) If we try some of the techniques that we employed in our earlier chapters,we will see that they are really expansions.Given a home directory that looks like this:
we could carry out the following expansions:
and:
or even:
and looking beyond our home directory:
Pathname Expansion Of Hidden Files
As we know,filenames that begin with a period character are hidden.Pathname expansion also respects this behavior.An expansion such as:
echo*
does not reveal hidden files.
It might appear at first glance that we could include hidden files in an expansion by starting the pattern with a leading period,like this:
echo .*
It almost works.However,if we examine the results closely,we will see that the names "." and ".." will also appear in the results.Since these names refer to the current working directory and its parent directory,using this pattern will likely produce an incorrect result.We can see this if we try the command:
ls -d.* | less
To correctly perform pathname expansion in this situation,we have to employ a more specific pattern.This will work correctly:
ls -d .[!.]?*
This pattern expands into every filename that begins with a period,does not include a second period,contains at least one additional character and can be followed by any other characters.This will work correctly with most hidden files (though it still won't include filenames with multiple leading periods). The ls command with the -A option ("almost all") will provide a correct listing of hidden files;
ls -A
Wave line expansion (波浪线展开)
As you may recall from our introduction to the cd command,the tilde(波浪字符) character("~") has a special meaning.When used at the beginning of a word,it expands into the name of the home directory of the name user,or if no user is named,the home directory of the current user:
If user "darui" has an account,then:
Arithmetic expression expansion
The shell allow arithmetic to be performed by expansion.This allow us to use the shell prompt as a calculator:
Arithmetic expansion uses the form:
$((expression))
where expression is an arithmetic expression consisting of values and arithmetic operators.
Arithmetic expansion only supports integers(whole numbers,no decimals(小数)),but can perform quite a number of different operations.Here are a few of the supported operators:
Table 8-1:Arithmetic Operators
Operator | Description |
+ | Addtion |
- | Subtraction |
* | Multiplication |
/ | Division(but remember,since expansion only supports integer arithmetic,results are integers.) |
% | Modulo,which simply means,"remainder". |
** | Exponentiation(取幂) |
Spaces are not significant in arithmetic expressions and expressions may be nested(嵌套).For example,to multiply five squared by three:
Single parenthses may be used to group multiple subexpressions.With this technique,we can rewrite the example above and get the same result using a single expansion instead of two:
Here is an example using the division and remainder(剩余物) operator.Notice the effect of integer division:
Arithmetic expansion is covered in greater detail in Chapter 35.
Brace expansion(花括号展开)
Perhaps the strangest expansion is called brace expansion.With it,you can create multiple text strings from a pattern containning braces.Here's an example:
Patterns to be brace expanded may contain a leading portion(部分) called a preamble(序文,电报报头) and a trailing portion called a postscript.(附言)The brace expression itself may contain either a comma-separated(逗号分隔) list of strings,or a range of integers or single characters.The pattern may not contain embeded(植入的,内含的) whitespace.Here is an example using a range of integers:
A range of letters in reverse order:
Brace expansions may be nested:
So what is this good for?The most common application is to make lists of files or directories to be created.For example,if we were photographers and had a large photo collection of images that we wanted to organize into years and months,the first thing we might do is create a series of directories named in numeric "Year-month" format.This way,the directory names will sort in chronological(按时间的前后顺序排列的) order.We could type out a complete list of directories,but that's a lot of work and it's error-prone(易错的) too.Instead,we could do this:
Pretty slick!(顺利而有效的,不费力的)
Command expansion
We're only going to touch briefly on parameter expansion in this chapter,but we'll be covering it extensively(广泛地) later.It's a feature that is more useful in shell scripts than directly on the command line.Many of its capabilities(能做某事的素质,能力) have to do with the system's ability to store small chunks of data and to give each chunk a name.Many such chunks,more properly called variables,are available for your examination.For example,the variable named "USER" contains your user name.To invoke parameter expansion and reveal the contents of USER you would do this:
To see a list of available variables,try this:
You may have noticed that with other types of expansion,if you mistype a pattern,the expansion will not take place and the echo command will simply display the mistyped pattern.With parameter expansion,if you misspell the name of a variable,the expansion will still take place,but will result in an empty string:
Command substitution(替换)
Command substitution allows us to use the output of a command as an expansion:
One of my favorites goes something like this:
Here we passed the results of which cp as an argument to the ls command,thereby(因此) getting the listing of the cp program without having to know its full pathname.We are not limited to just simple commands.Entire pipelines can be used (only partial(局限,部分) output shown):
In this example,the results of the pipeline became the argument list of the file command.
There is an alternate (代替的,此处另一种) syntax for command substitution in older shell programs which is also supported in bash.It uses back-quotes(倒引号) instead of the dollar sign and parentheses(圆括号):
Quote(引用)
Now that we've seen how many ways the shell can perform expansions,it's time to learn how we can control it.Take for example:
or:
In the first example,word-splitting by the shell removed extra whitespace from the echo command's list of arguments.In the second example,parameter expansion substituted an empty string for the value of "$1"because it was an undefined variable.The shell provides a mechanism called quoting to selectively suppress unwanted expansions.(shell提供了一个叫引用机制来有选择地禁止不需要的展开)
Double quote
The first type of quoting we will look at is double quotes.If you place text inside double quotes,all the special characters used by the shell lose their special meaning and are treated as ordinary characters.The exceptions(例外) $,\(backslash),and `(back-quote).This means that word-splitting,pathname expansion,tilde(波浪线) expansion,and brace(花括号) expansion are suppressed,but parameter expansion,arithmetic expansion,and command substitution are still carried out.Using double quotes,we can cope with filenames containing embedded spaces.Say we were the unfortunate victim of a file called two words.txt. If we tried to use this on the command line,word-splitting would cause this to be treated as two separate arguments rather than the desired single argument;
By using the double quotes,we stop the word-splitting and get the desired result;further,we can even repair the damage:
There!Now we don't have to keep typing those pesky double quotes.
Remember,parameter expansion,arithmetic expansion,and command substitution still take place within double quotes:
We should take a moment to look at the effect of double quotes on command substitution.First let's look a little deeper at how word splitting works.In our earlier example,we saw how word-splitting appears to remove extra spaces in our text:
By default,word-splitting looks for the presence(存在) of spaces,tabs,and newlines (linefeed characters) and treats them as delimiters(分隔符)between words.This means that unquoted spaces,tabs,and newlines are not considered to be part of the text.They only serve as separators.(在默认情况下,单词分割机制会在单词中寻找空格,制表符,和换行符,并把它们看作单调之间的界定符。这意味着无引用 的空格,制表符和换行符都不是文本的一部分,它们只作为分隔符使用)Since they separate the words into different arguments,our example command line contains a command followed by four distinct arguments.If we add double quotes:
word-splitting is suppressed and the embedded spaces are not treated as delimiters,rather they become part of the argument.Once the double quotes are added,our command line contains a command followed by a single argument.(???????????搞不懂这句话啥意思)
The fact that newlines are considered delimiters by the word-splitting mechanism causes an interesting,albeit subtle,effect on command substitution.Consider the following:
第一个例子中没有引用的命令替换导致命令行包含38个参数,因为单词分割机制,cal执行出来的包含空格和换行符的结果,被当成了定界符。在二个例子中,命令行只有一个参数,参数中包括嵌入的空格和换行符。
Single quotes
If we need to suppress all expansions,we use single quotes.Here is a comparison(比较) of unquoted,double quotes,and single quotes;
As we can see,with each succeeding level of quoting,more and more of the expansions are suppressed.
Escape character(转义字符)
Sometimes we only want to quote a single character.To do this,we can precede(在那之前,先于) a character with a backslash,which in this context is called the escape character.Often this is done inside double quotes to selectively prevent an expansion:
It is also common to use escaping to eliminate the special meaning of a character in a filename.For example,it is possible to use characters in filenames that normally have special meaning to the shell.These would include "$","!","&"," ",and others.To include a special character in a filename you can to this:
To allow a backslash character to appear,escape it by typing "\".Note that within single quotes,the backslash loses its special meaning and is treated as an ordinary character.
可以把没用到single quote的\叫做escape character,把用到single quote 的叫做blackslash,哈哈
Backslash Escape Sequences
In addition to its role as the escape character,the backslash is also used as part of a notation to represent certain special characters called control codes.The first thirty-two characters in the ASCII coding scheme are used to transmit commands to teletype-like devices.Some of these codes are familiar(tab,backspace,linefeed,and carriage retrun),while others are not(null,end-of-transmission,and acknowlege)
Escape Sequence | Meaning |
\a | Bell("Alert" -causes the computer to beep) |
\b | Backspace |
\n | Newline.On Unix-like systems,this produces a linefeed |
\r | Carriage return退格符 |
\t | Tab |
The table above lists some of the common backslash escape sequences.The idea behind this representation using the backslash originated in the C programming language and has been adopted by many others,including the shell.
Adding the '-e' option to echo will enable interpretaion(解释) of escape sequences.You may also place them inside $' '.Here,using the sleep command,a single program that just waits for the specified number of seconds and then exits,we can create a primitive countdown timer:
!!!!在用到上面那些转义字符序列的时候,我们需要加上-e选项。
sleep 10;echo -e "Time's up \a"
We could also do this:
sleep 10;echo "Time's up" $'\a'
Sum-up
As we move forward with using the shell,we will find that expansions and quoting will be used with increasing frequency(频率),so it makes sense to get a good understanding of the way they works.In fact,it could be argued that they are the most important subjects to learn about the shell.Without a proper understanding of expansion,the shell will always be a source of mystery and confusion,and much of it potential power wasted.