1. 程式人生 > >See the world from the eyes of shell

See the world from the eyes of shell

存在 clu ets mea appears commands world red contex

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.

See the world from the eyes of shell