linux 中输入bash,Linux上Bash Shell编程

许淳
2023-12-01

Linux下Bash Shell编程

Bash Shell Programming in Linux

Linux下Bash Shell编程

Bash what?

进阶的内容是什么?

Okay, I grant that this page mightrepresent a leap from the familiar to the alien without much warning. Here aresome explananatory notes:

好吧,我承认,本页内容可能在没有给你足够警告的情况下,带领你从熟悉程度飞跃到更高阶段(难道alien是火星人?)下面有一些解释说明:

UnderLinux, there are some powerful tools that for all practical purposes areunavailable under Windows (I can imagine all the old Linux hands saying"Duh!").

在Linux中,有很多Windows中没有的强大的工具用于实用目标(可以想象所有Linux老用户喊“咄”的情景)。

·One of these tools is something called"shell programming". This means writing code that a command shellexecutes.

·这些工具中的一个被称为“shell编程”。就是说命令外壳执行编写的代码。

·There is something like this underWindows, but as usual, the Windows version is a weak imitation.

·在Windows下,有一些类似的工具,不过一般情况,Windows版本是薄弱的纺织品。

·The most common Linux shell is named"Bash". The name comes from "Bourne Again SHell," which, inturn ... (imagine a lengthy

recursion terminating in a caveman's grunt).

·Linux最常见的外壳程序名为“Bash”。名称来自于“Bourne

Again SHell”。这个,要反过来说..(设想一个漫长的递归终结于穴居人的咕噜)。

·

·There are many other shells available.Unless there is a compelling reason not to, I recommend that people stick tothe Bash

shell, because this increases the chance that your scripts will beportable between machines, distributions, even operating systems.

·也有很多其他可用的外壳程序。没有特别原因时,我建议大家专注于Bash程序,因为它能提升你的脚本在服务器、发布甚至操作系统上的移植机会。

·I'll be showing some very basic examplesof Bash shell programming on this page, and I want to say at the outset thatshell

programming is an art, not a science. That means there is always someother way to do the same thing.

·我会在本页展示一些非常基础的Bash shell编程例子,并且我起初想说的是,Shell编程是一门艺术,而不是技术。也就是说,总有很多其他方式实现相同的目的。

·

·Because shell programming is an art,please don't write to say, "Wow, that was a really inefficient way to dosuch-and-such."

Please do write (message page) to report actual errors.

·由于shell编程是一门艺术,请不要写信说“哦,Shell在做这样或那样的事情时真的很没效率”。请写(信息页)报告实际的错误。

·

·If this page seems too sketchy andelementary for your taste, you can choose from among the more advancedresources in .

·如果本页的信息看起来太简单,太初级的话,可以从中选择更高级的资源。

Introduction

简介

·Early computers had a teletype machinewith a keyboard for I/O. Later, glass terminals became the norm, but thebehavior

was much the same — a keyboard, a screen, a text display. A programwas responsible for mediating the transaction between the operator and themachine, and as the years passed this program (the command interpreter orshell) became more sophisticated.

·早期计算机有一个打字机,使用键盘进行I/O。后来,纯平显示终端普及,但是行为却非常相似—一个键盘,一个显示器,一个文本显示器。程序衔接操作人和机器之间的事务,并且经历多年之后,程序(命令解析或者shell)也变得越来越复杂。

·At this stage the command shell has becomerather too sophisticated, typically having a dozen ways to do any particularthing.

In this page I will try to limit myself to describing a handful ofuseful operations, based not on listing everything that can be done, but onsolving specific problems. There are some at the bottom of this page for thosewanting more depth.

·现阶段,命令行变得太复杂,尤其有很多方式特定的事情。在本页,我会在不列举所有的操作但是能解决问题的基础上,尝试限制自己去描述一些有用的操作。有些更有深度的信息在本页的底部。

·

Preliminaries

写在正文之前

·There are two primary ways to use theshell: interactively and by writing shell scripts.

·使用shell有两种主要方式:交互式和编写shell脚本的方式。

oIn theinteractive mode, the usertypes a single command (or a short string of commands) and the result isprinted out.

o在交互模式中,用户输入单个命令(或者短的命令字符串),然后结果被输出。

oInshell scripting, the user typesanything from a few lines to an entire program into a text editor, then executesthe

resulting text file as a shell script.

o使用shell脚本时,用户输入几行代码或者整个程序到编辑器中,然后以shell脚本方式运行。

oIt is often the case that an interactivesession becomes a shell scripting session, once things get too complicated forsimple

interactive line entries, or because a specific sequence of commandsappears to be generally useful and worth preserving.

o交互模式的会话常常逐步变成了shell脚本的会话,一旦需求在单一交互式入口变的复杂,或者由于代码的特定顺序变得有用,并且需要被保障时。

·In a modern Linux environment the user canhave more than one shell open at a time, either by moving between a sequence

ofindependent "virtual terminals" in a text-only environment, or byopening any number of shell windows in the X Windows environment.

·现在,在Linux环境下,用户可以同时打开多个shell,要么在多个独立文本环境的虚拟终端间切换位置,要么在多窗口环境中打开多个shell窗口。

·

·The advantage of having more than oneshell available is that one shell can be used for testing one command at atime, while

another might provide a text editor for assembling single commandsinto a shell program.

·同时可以有多个有效shell脚本的优点是,可以在一个文本编辑器编写代码到程序的同时,另一个窗口用于命令测试。

·I don't want to get toodistribution-specific, but if you are not hosting X Windows and want more thanone simultaneous shell

session, with many current distributions you can switchbetween "virtual terminals" by pressing Ctrl+Alt+F(n), n typicallybetween 1 and 6.

·我不想搞特殊分配,但如果你没有使用多窗口模式并且想同时操作多个shell会话,在很多现在的版本中,可以使用Ctrl+Alt+F(n)在多个虚拟终端间切换,n通常在1到6。

·

·In an environment that supports X Windows,simply open any desired number of command shell windows and move between them.

·在支持多窗口模式的环境,直接打开多个shell命令窗口,并且可以在窗口间切换。

Simple Stuff

简单例子

·First, a convention. I'll list things foryou to type in this format:

·首先,按照惯例,我会按照下面格式列出你需要输入的内容:

$ date

I will list the computer's reply like this:

我会按下面格式列出计算机的响应:

Tue Dec 23 10:52:51 PST 2003

Notice the "$" symbol in the user entry above. This is a genericshell prompt, and yours will almost certainly look different (but it willinclude a similar symbol).

I'll be using one of two prompts (this is a commonconvention, worth remembering): I'll use "$" to refer to a normaluser session, and "#" to refer to a root session.

注意上面的“$”符号是用户输入。这是个常规的shell符号,当然肯定也可以看到其他不同的符号(不过会包含类似的符号)。我会用一到两种符号(这是个常见的习惯,值得记住):我会用“$”提交到用户会话,用“#”提交root会话。

·NOTE:Avoid using root sessions and permissions unless it is required.Misused

root authority can cause very serious harm to your system. Since thisis a tutorial in which you will want to experiment with different commands,limit the chance for harm by doing so as an ordinary user.

·注意:避免使用root会话和权限,除非需要这些权限。误用root认证会导致对系统非常严重的破坏。因为这是你以后使用不同命令的经验,使用普通用户权限可以减少系统被破坏的机会。

·

·To put this another way, enter thisexample:

·使用另一种方式确定,输入下面例子:

# whoami

root

If your session produced the result shown above, please — log out andbecome an ordinary user.

如果你的会话生成上面显示的结果,请—注销后以普通用户登录。

·In shell programming,spaces matter.If you see spaces between words andcharacters

in these examples, be sure to include the spaces.

·在shell编程中,空格问题。如果你在例子的字和字符间看到空格,请确信包含这些空格。

·In shell programming,case matters also.If you don't get the results shown onthis

page, look at the case of your entries.

·在shell编程中,也有大小写问题。如果没有获取到结果,查看输入的大小写。

Where are you?

你在哪儿?

·As you may be aware, a Linux filesystem isin the form of a large tree with many branches called"subdirectories". When you

issue a shell command, it is oftennecessary to know where you are in the "tree". Type this example:

·你可能意识到了,Linux的文件系统是一个巨大的树形结构,包含了很多称为“子目录的”分支。当你使用shell命令时,通常需要知道你在这个“树”中的位置。输入下面的例子:

$ pwd

/path/path/path

When you try this example ("pwd" means "print workingdirectory"), your current working directory will be printed.

当你尝试这个例子(“pwd”表示“打印工作目录”),你当前的工作路径会被打印出来。

·You can decide where you are in the tree.Type this example:

·可以决定在树形路径的位置,输入以下例子:

$ cd ~

$ pwd

/home/username

The symbol "~" is a special shortcut character that can be usedto refer to your home directory. You could have typed this —

符号“~”是特定的可以用于应用到用户的home路径的快捷方式。可以输入:

$ cd /home/username

— and accomplished the same result, but if you think about it, the"~" character is more portable. Later, when you are writing shellscripts, you might want a command

that moves to any user's home directory.

—会达到相同的效果,但如果考虑以下的话,“~”字符更方便。以后,当你编写shell脚本时,你可能希望有个命令可以移动到任何用户的home路径。

Listing Files

文件列表

·Directories contain files, and you canlist them in a simple, compact format:

·目录包含文件,可以以简单,简洁的格式列出文件:

$ ls

filename filename filename ...

Or you can list them in more detail:

或者,列出更详细的信息:

$ ls -la

(detailed list, one file per line)

And, very important, to find out what a command's options are, use the"man" (manual) command:

还有,非常重要的是,使用“man”命令查看命令的选项:

$ man ls

(manual page for "ls")

NOTE:The "man" command allows youto learn a command's options. You still have to remember the command's name.

注意:“man“命令让你学习命令的选项。你依然需要记住命令的名称。

To find files by name:

根据名称查找文件:

$ find . -name '*.jpg'

(list of files with .jpg suffix in currentand all child directories)

(列出在当前目录和所有子目录中的.jpg后缀的文件。)

To create a text diagram of the directory tree:

创建目录树的文本图表:

$ tree -d .

(diagram of the directory tree from thecurrent directory)

(从当前路径得到的路径图表)

The "tree" command is less useful now that directory trees havebecome so complicated, and now that most distributions support X Windows andsophisticated filesystem

browsers.

“tree“,命令没那么有用了,现在的目录树已经变得很复杂并且现在多数发布版本都支持多窗口和复杂的文件系统浏览器。

Examining Files

检查文件

·There are a number of things you can do tofind out more about the files in the list. Here are just a few:

·要找出文件列表中更多的信息,有很多事情要做。下面是少部分:

The "file" command tries to identify files by examining theircontents:

“file“命令通过检查文件内容标志文件。

$ file tux_small.png

tux_small.png: PNG image data, 128 x 151,8-bit/color RGB, non-interlaced

The next example uses the obscurely named "cat" command. Itprints the contents of a file. Unfortunately if the file's contents are notreadable, they get printed

anyway.

下一个例子隐式使用名为“cat”的命令。它打印文件内容。很不幸运,如果文件内容不可读,它也会打印出来(乱码)。

$ cat zipcodes.txt

(prints the entire contents of a filenamed "zipcodes.txt")

If a file is too long to be viewed on one page, you can say:

如果文件太长而不能在一页内查看,可以输入:

$ more zipcodes.txt

(prints file one screenful at a time)

You can also use "grep" to print only those parts of a file youare interested in:

也可以使用“grep”只打印那些你感兴趣的部分:

$ grep 10001 zipcodes.txt

(prints only those lines that have thecharacter string "10001" in them)

The "grep" command is very useful, unfortunately it has adifficult-to-remember name. Be sure to:

“grep”命令非常有用,不巧的是它有个很难记住的名字一定要:

$ man grep

There are many, many more shell commands tolearn and to use. You may want to browse the list of for more detail.

有很多shell命令需要学习和使用。你可能需要浏览更加详细的列表。

Pipelines andRedirection

·You can use apipeline (symbolized by "|") to make the output of one command serveas the input to another command.This idea can beused to create a combination of commands to accomplish something no singlecommand can do.

·可以使用管道(使用“|”符号标识)将一个命令的输出作为另一个命令的输入。这个方法用于创建合并的命令集以完成一些单个命令无法完成的事情。

·

Enter this command:

输入命令:

$ echo "cherry apple peach"

cherry apple peach

Okay, let's say we want to sort these words alphabetically. There is acommand "sort", but it sorts entire lines, not words, so we need tobreak this single line into

individual lines, one line per word.

好的,比方说我们想要按字母顺序排列这些单词。有一个”sort”命令,但是会排序整行数据,而不是按单词排序,所以我们需要将这行内容分成独立的行,每行一个单词。

Step one: pipe the output of "echo" into a translation (tr)command that will replace spaces with linefeeds (represented by"\n"):

第一步:导入“echo”命令的输出信息到“tr”命令,“tr”会使用换行(用“\n”表示)替换空格:

$ echo "cherry apple peach" |tr " " "\n"

cherry

apple

peach

Success: each word appears on a separate line. Now we are ready to sort.

成功:每个单词输出一行。现在我们可以排序了。

Step two: add the sort command:

第二步:添加排序命令:

$ echo "cherry apple peach" |tr " " "\n" | sort

apple

cherry

peach

Let's try reversing the order of the sort:

我们尝试翻转排序顺序:

$ echo "cherry apple peach" |tr " " "\n" | sort -r

peach

cherry

apple

·Remember:A pipeline ("|") takes the output of one command and makesit

the input to another command.

·请记住:管道(“|”)获得一个命令的输出并且将输出作为另一个命令的输入。

·Normally the output from commands isprinted on the screen. But using the symbol ">", you can redirectthe output to a file:

·一般情况,命令的输出会被打印到屏幕。但是使用“>”,可以将输入导出到文件。

$ date > RightNow.txt

$ cat RightNow.txt

Tue Dec 23 14:43:33 PST 2003

The above example used ">" to replace the content of anyexisting file having the name "RightNow.txt". To append new data toan existing file, use ">>" instead:

上面的例子使用“>”替换名为“RightNow.txt”的文件内容。要增加新的信息到文件中,使用“>>”替代:

$ date >> RightNow.txt

$ cat RightNow.txt

Tue Dec 23 14:43:33 PST 2003

Tue Dec 23 14:46:10 PST 2003

·Remember:Use ">" to overwrite any existing file, use">>" to append

to any existing file. In both cases, if nofile exists, one is created.

·请记住:使用“>”覆盖任何已存在文件内容,使用“>>”增加内容到已存在文件。相同的是,如果文件不存在,会创建文件。

·Many commands have inputs as well asoutputs. The input defaults to the keyboard, the output defaults to the screen.

·很多命令有输入也有输出。输入默认通过键盘,输出默认到屏幕。

·To redirect the output to a file, use">" or ">>" as shown above.

·要转存输出到文件中,使用如上所示的“>”或“>>”。

·To make the output of acommandserve as the input of another command, use "|".

·要使一个命令的输出作为另一个命令的输入,使用“|”。

·To make the contents of afileserve as the input to a command, use "

·要使一个文件的内容作为命令的输入,使用“

$ wc < RightNow.txt

2 12 58

As is so often the case in shell programming, there is at least one otherway to produce the above result:

Shell编程中常常有这种情况,至少有另一种方法达到上边的结果:

$ cat RightNow.txt | wc

2 12 58

Shell Script Basics

Shell脚本基础

·A shell script is a plain-text file thatcontains shell commands. It can be executed by typing its name into a shell, orby

placing its name in another shell script.

·Shell脚本时包含shell命令的文本文件。可以在通过输入文件名到shell执行,或者在另外一个shell脚本中使用它的名称。

·To be executable, a shell script file mustmeet some conditions:

·要作为可执行文件,shell脚本文件必须满足一些条件:

oThe file must have a special first linethat names an appropriate command processor. For this tutorial, the followingwill work

in most cases:

o文件必须有特定的首行,确定一个合适的命令处理器。本片指导中,大多数情况使用下面的内容:

#!/bin/bash

If this example doesn't work, you will need to find out where your Bashshell executable is located and substitute that location in the above example.Here is one

way to find out:

如果这个例子不能运行,你需要找出Bash shell可执行文件加载的路径并替换上面例子的路径。下面是一种确定方法:

oThe file must be made executable bychanging its permission bits. An example:

oBash shell文件必须通过改变权限位的方式使它成为看执行文件。例如:

$ chmod +x (shell script filename)

·A shell script file may optionally have anidentifying suffix, like ".sh". This only helps the user rememberwhich files

are which. The command processor responsible for executing the fileuses the executable bit, plus the file's first line, to decide how to handle ashell script file.

·Shell脚本文件可以使用标志性的扩展名,如:“.sh”。这个仅能帮助用户记忆文件类型。命令响应处理器使用文件的可执行控制位,添加在文件的第一行,以决定shell文件的处理方式。

·One normally executes a shell script thisway:

·一般使用下面方式运行shell脚本:

$ ./scriptname.sh

This special entry is a way to tell the command processor that the desiredscript is located in the current directory. Always remember: if you cannot getyour shell script to run, remember this trick to provide

its location as wellas its name.

这种方式是告知命令处理器,它要处理的脚本位于当前路径。一定要记住:如果shell脚本不能运行,记得这招:提供文件名称时,也提供它的路径。

First Shell Script

第一个Shell脚本

·This will get you past the details ofwriting and launching a simple script.

·下面让你通过编写和调用简单shell脚本的细节。

1.Choose a text editor you want to use. Itcan be a command-line editor like emacs, pico or

vi, or an X Windows editor ifyou have this option.

2.Run your choice of editor and type thefollowing lines:

3.

4. #!/bin/bash

5. echo "Hello, world."

6.

1.选项你想用的文本编辑器。可以是emacs、pico、vi这样的命令行编辑器,或者是多窗口的编辑器(如果你有的话)。

2.运行编辑器,并输入下面内容:

3.

NOTE:Be sure to place a linefeed at the endof your script.

注意:请确定在你脚本的结尾添加换行符。

Forgetting a terminating linefeedis a common beginner's error.

忘记结束的换行符是新手常见的错误。

6.Save the file in the current workingdirectory as "myscript.sh".

7.Move from the text editor to a commandshell.

8.From the command shell, type this:

$ chmod +x myscript.sh

9.To execute the script, type this:

$ ./myscript.shHello, world.

·These steps will become second nature soonenough.

Tests and Branching

·Bash shell scripts can perform, and act on,various kinds of tests. This will be just the most basic introduction — see

thereference material at for more on this rather baroque topic.

·To follow these andother examples that involve multiline shell scripts, please set up to edit andrun a test script

file (let's call it "myscript.sh") that you can useto enter and test various options. And remember that the examples won't includethe all-important first line of the script (see script examples above) — itwill be assumed to exist in each case.

Also, to save time, you may want to copy some of the shell code examplesfrom this page directly into your editor.

·Here is an example of a test and branch:

·

·if [-e . ]

·then

·echo "Yes."

·else

·echo "No."

·fi

·

Run the test script:

$ ./myscript.shYes.

We created a test (the part of the script between "[" and"]") which tested whether a particular element existed("-e"). Because the symbol "." in this context means

thecurrent directory, the test succeeded. Try replacing the "." withsomething that is not present in the current directory, example"xyz". See how the outcome changes.

It is important to realize that "[" is an alias for the command"test". The script could have been written as:

if test -e .

then

echo "Yes."

else

echo "No."

fi

NOTE:Be sure to read the "test" manpage to find out all the different tests that are available:

$ man test

Before we move on, there is a perversity about tests in Bash shells that Iwant to discuss. It turns out, because of a historical accident that now mightas well be

cast in concrete, when a test is conducted or a command returns aresult value, the numerical value for "true" is 0, and"false" is 1. Those of you who have some programming experience willlikely find this reversal of intuition as annoying as I do.

Here is a way to get the result of the most recent logical test (and toshow the weird reversal described above):

$ test -e .$ echo $?0

$ test -e xyz$ echo $?1

Please remember this reversal, because it confounds the process ofthinking through, and constructing, logical tests. For example, you may want towrite a shortcut

form for a test that only acts on one kind of result:

$ test -e . && echo"Yes."Yes.

This sort of shorthand relies on some knowledge of logical processing — ifthe left-hand part of an AND test yields "true", then the right-handpart must also be evaluated,

and so it is. But the numerical "true"value for the left-hand test is 0, which would argue for the opposite logic.

Just to show how perverse this all is, here is an example of Bash logicaltesting that comes out the opposite way:

$ echo $(( 0 && 0 ))0

$ echo $(( 1 && 0 ))0

$ echo $(( 0 && 1 ))0

$ echo $(( 1 && 1 ))1

Yes, just as you would expect. So do be on guard against this shell"gotcha", which only affects the outcome of tests and command resultvalues. It probably will not

surprise you to learn that no one mentions thisstrange anomaly in the official Bash documentation.

A couple of rules about logical operators used as branches:

oIf you write "test &&command", the command will only be executed if the testsucceeds.

oIf you write "test || command",the command will only be executed if the testfails.

Run these tests:

$ true && echo "Yes."Yes.

$ false || echo "Yes."Yes.

Notice that the outcomes are entirely in keeping with one's intuitionabout such logical comparisons, and all is well as long as you don't thinkabout the fact that

true equals 0. :)

Here's another scheme commonly seen in shell script programming andinteractive sessions:

$ command1 && command2 &&command3 && command4

This line of code will not run the next command in the sequence unless theprior command has returned "true", meaning no errors. It is a way toavoid running a command

if a required prior outcome is not present.

Loops andRepetition

·Here are some examples of loop operators:

·

·for fnin *; do

·echo "$fn"

·done

·

In this example, the "*" is expanded by the shell to a list ofall the files in the current directory, then each filename is applied to theloop control area. In such

a construct, any whitespace-delimited list will do:

for fn in tom dickharry; do

echo "$fn"

done

$ ./myscript.shtomdickharry

This method will work for any list that uses spaces as delimiters. Butwhat happens if you must parse a list that must be delimited by linefeedsinstead of spaces,

such as the case of a list of filenames or paths thatcontain spaces as part of their names?

You can solve such a problem this way (there are other solutions):

ls -1 | while readfn; do

echo "$fn"

done

This example uses an option to "ls" (note: the option is"-" followed by the numerical digit "1",not alowercase "L") that formats file listings with one

name per line,then this list is pipelined to a routine that reads lines until there are nomore to read. This meets the requirement that linefeeds become the delimitersbetween list elements, not spaces.

There is plenty more to this topic. Please refer to the list of for more.

Using Numbers inScripts

·Contrary to a sometimes-expressed view,numbers can easily be accommodated in scripts. Example:

·

·n=1

·while[ $n -le 6 ]; do

·echo $n

·let n++

·done

·

$ ./myscript.sh123456

Notice the "let" command, which treats its argument in a waymeant to accommodate numbers.

Here is a somewhat more complex example:

y=1

while [ $y -le 12 ];do

x=1

while [ $x -le 12 ]; do

printf "% 4d" $(( $x * $y))

let x++

done

echo ""

let y++

done

$ ./myscript.sh

1  2   3   4  5   6   7  8   9  10 11  12

2  4   6   8 10  12  14 16  18  20 22  24

3  6   9  12 15  18  21 24  27  30 33  36

4  8  12  16 20  24  28 32  36  40  44  48

5 10  15  20 25  30  35 40  45  50 55  60

6 12  18  24 30  36  42 48  54  60 66  72

7 14  21  28 35  42  49 56  63  70 77  84

8 16  24  32 40  48  56 64  72  80 88  96

9 18  27  36 45  54  63 72  81  90  99108

10  20  30 40  50  60 70  80  90 100 110 120

11 22  33  44 55  66  77 88  99 110 121 132

12 24  36  48 60  72  84  96108 120 132 144

Coping with userinput

·Here is an example that relies on userinput to decide what to do. It exploits a shell feature as an easy way tocreate a

menu of choices:

·

·PS3="Choose(1-5):"

·echo"Choose from the list below."

·selectname in red green blue yellow magenta

·do

·break

·done

·echo"You chose $name."

·

When run, it looks like this:

$ ./myscript.sh

Choose from the listbelow.

1) red

2) green

3) blue

4) yellow

5) magenta

Choose (1-5):4

You chose yellow.

As written, this menu code won't catch some kinds of errors (like a numberthat is out of range). In any application where the user choice must fall intodefined bounds,

be sure to perform a test on the result before using it.Example:

if ["$name" = "" ]; then

echo "Error in entry."

exit 1

fi

An advanced example with numbers and user input

·Here is an example guessing game that tiestogether some of the elements we've covered so far:

·

·secretNumber=$((((`date +%N` / 1000) % 100) +1 ))

·guess=-1

·while[ "$guess" != "$secretNumber" ]; do

·echo -n "I am thinking of a numberbetween 1 and 100. Enter your guess:"

·read guess

·if [ "$guess" = "" ];then

·echo "Please enter anumber."

·elif [ "$guess" ="$secretNumber" ]; then

·echo -e "\aYes! $guess is thecorrect answer!"

·elif [ "$secretNumber" -gt"$guess" ]; then

·echo "The secret number islarger than your guess. Try again."

·else

·echo "The secret number issmaller than your guess. Try again."

·fi

·done

·

Please study this example carefully, and refer to the reference materialsin to understand some of the methods.

Creating and usingarrays

·Shell arrays are relatively easy toconstruct. Example:

·

·array=(redgreen blue yellow magenta)

·len=${#array[*]}

·echo"The array has $len members. They are:"

·i=0

·while[ $i -lt $len ]; do

·echo "$i: ${array[$i]}"

·let i++

·done

·

Run this example:

$ ./myscript.sh

The array has 5members. They are:

0: red

1: green

2: blue

3: yellow

4: magenta

Now, before you decide this is a silly, rather useless example, replaceone line of the script and run it again:

array=(`ls`)

See what difference this makes (and think of all the kinds of lists youmight create for this line).

Strings andsubstrings

·It's useful to be able to take stringsapart and put them together in different ways. Here is how to select asubstring from

a string:

·

·string="thisis a substring test"

·substring=${string:10:9}

·

In this example, thevariable "substring" contains the

word"substring". Remember this rule:

substring=${string_variable_name:starting_position:length}

The string starting position is zero-based.

Searching and Replacing Substrings within Strings

·In this method you can replace one or moreinstances of a string with another string. Here is the basic syntax:

·

·alpha="Thisis a test string in which the word \"test\" is replaced."

·beta="${alpha/test/replace}"

·

The string "beta" now contains an edited version of the originalstring in which thefirst case of the word "test" has beenreplaced by "replace". To replace

all cases, not just thefirst, use this syntax:

beta="${alpha//test/replace}"

Note the double "//" symbol.

Here is an example in which we replace one string with another in amulti-line block of text:

list="cricketfrog cat dog"

poem="I wanna bea x\n\

A x is what I'd loveto be\n\

If I became a x\n\

How happy I wouldbe.\n"

for critter in $list;do

echo -e ${poem//x/$critter}

done

Run this example:

$ ./myscript.sh

I wanna be a cricket

A cricket is what I'dlove to be

If I became a cricket

How happy I would be.

I wanna be a frog

A frog is what I'dlove to be

If I became a frog

How happy I would be.

I wanna be a cat

A cat is what I'dlove to be

If I became a cat

How happy I would be.

I wanna be a dog

A dog is what I'dlove to be

If I became a dog

How happy I would be.

Silly example, huh? It should be obvious that this search & replacecapability could have many more useful purposes.

More obscure but useful string operations

·Here is a way to isolate something usefulfrom a large, even multi-line, string. As above, this method relies onenclosing

a variable name in curly braces, then aplying a special operator toachieve a particular result.

Here is a list of four such operators:

oOperator "#" means "deletefrom the left, to the first case of what follows."

o

o$ x="This is my test string."

o$ echo ${x#* }

o

ois my test string.

o

o

oOperator "##" means "deletefrom the left, to the last case of what follows."

o

o$ x="This is my test string."

o$ echo ${x##* }

o

ostring.

o

o

oOperator "%" means "deletefrom the right, to the first case of what follows."

o

o$ x="This is my test string."

o$ echo ${x% *}

o

oThis is my test

o

o

oOperator "%%" means "deletefrom the right, to the last case of what follows."

o

o$ x="This is my test string."

o$ echo ${x%% *}

o

oThis

o

o

I find these operators particularly useful in parsing multi-line strings.Let's say I want to isolate a particular IP address from the output of the"ifconfig" command.

Here's how I would proceed:

$ x=`/sbin/ifconfig`

$ echo $x

eth0

Link encap:Ethernet  HWaddr 00:0D:56:0C:8D:10

inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0

inet6 addr:fe80::20d:56ff:fe0c:8d10/64 Scope:Link

UP BROADCAST RUNNING MULTICAST  MTU:1500 Metric:1

RX packets:253339 errors:0 dropped:0overruns:0 frame:0

TX packets:423729 errors:0 dropped:0overruns:0 carrier:0

collisions:0 txqueuelen:1000

RX bytes:36150085 (34.4 MiB)  TX bytes:496768499 (473.7 MiB)

Base address:0xecc0Memory:fe4e0000-fe500000

lo

Link encap:Local Loopback

inet addr:127.0.0.1  Mask:255.0.0.0

inet6 addr: ::1/128 Scope:Host

UP LOOPBACK RUNNING  MTU:16436 Metric:1

RX packets:109394 errors:0 dropped:0overruns:0 frame:0

TX packets:109394 errors:0 dropped:0overruns:0 carrier:0

collisions:0 txqueuelen:0

RX bytes:12372380 (11.7 MiB)  TX bytes:12372380 (11.7 MiB)

There's lots of information, more than we need. Let's say for the sake ofargument that I want the IP of "lo", the loopback interface. I couldspecify this:

$ y=${x#*inet addr:}

But, while gobbling text from the left, this search would stop at the IPaddress of eth0, not the desired interface. So I can specify it this way:

$ y=${x#*lo *inetaddr:}

As a last step I'll trim off all remaining text to the right:

$ y=${y%% *}

Leaving only the desired address.

It seems the "#" and "%" operators, and theirvariants, are able to accept a rather complex argument and sort through thecontent of large strings, including strings

with line breaks. This means I canuse the shell to directly filter content in some simple cases where I mighthave considered using sed or Perl.

Bash Version 3

I have always thought the inability to test for the presence of a stringor pattern (without using grep, sed or something similar) was a conspicuousweakness in shell

programming. Bash version 3, present on must current Linuxdistributions, addresses this lack by allowing regular expression matching.

Let's say we need to establish whether variable $x appears to be a socialsecurity number:

if [[ $x =~[0-9]{3}-[0-9]{2}-[0-9]{4} ]]

then

# process SSN

else

# print error message

fi

Notice the Perlish "=~" syntax and that the regular expressionappears withindouble brackets. A substantial number of regularexpression metacharacters are

supported, but not some of the Perl-specificextensions like \w, \d and \s.

Another Bash 3 feature is an improved brace expansion operator:

$ echo {a..z}

a b c d e f g h i j kl m n o p q r s t u v w x y z

for n in {0..5}

do

echo $n

done

0

1

2

3

4

5

Useful Links

Well, as long-winded as it turned out tobe, this page is supposed to be an introduction to shell programming, one thatjust touches the highlights. The linked

references below will provide a deeper understandingof the covered topics.

·A quick guide to writingscripts using the bash shell (Rutgers)

·Advanced Bash Scripting Guide (Linux DocumentationProject)

·Bash Reference Manual (GNUProject, downloadable versions)

Home|

Linux|

* Linux BaseAdventures in Ray TracingBash Script BeautifierBash Shell Programming in LinuxConsistent Network Device NamingDictionary access under LinuxDictionary front end using PHPInstalling Linux on a Dell XPS LaptopMobile Internet Access Using LinuxModelinesNetworkManagerNokiaNotes and Fixes for Fedora 17Running Fedora Linux on Dell LaptopsSecure Shell Fun and Games

Share  This Page

 类似资料: