精华内容
下载资源
问答
  • Linux Bash Shell编程(零):序与索引

    千次阅读 2020-08-18 17:08:42
    Linux Bash Shell编程(零):序与索引 序   本Linux Bash Shell编程教程共10节,主要为没有编程基础的运维工作者或想学习Linux Bash脚本的新手而写。教程中含有许多样例参考,全部都是可以执行的命令行或是完整...

    Linux Bash Shell编程(零):序与索引

      本Linux Bash Shell编程教程共10节,主要为没有编程基础的运维工作者或想学习Linux Bash脚本的新手而写。教程中含有许多样例参考,全部都是可以执行的命令行或是完整经过测试的Bash脚本文件,方便大家通过样例直观学习语法。内容较为基础简单(请大佬勿喷);但对较深入但我认为没有重要作用的内容(如函数等)没有写入,如果需要的话一段时间后可能会更新。本教程一定意义上也是笔者学习Linux Bash Shell 的笔记,希望与大家分享、共同进步,感谢大家的支持!


    索引

    展开全文
  • Linux下Bash Shell编程

    千次阅读 2013-02-21 23:44:59
    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 expl

    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脚本的方式。

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

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

    o   Inshell 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脚本方式运行。

    o   It 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+Fn)在多个虚拟终端间切换,n通常在16

    ·         

    ·        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脚本文件必须满足一些条件:

    o   The 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可执行文件加载的路径并替换上面例子的路径。下面是一种确定方法:

     

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

    o   Bash 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.sh
    Hello, 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.sh
    Yes.

    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:

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

    o   If 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.sh
    tom
    dick
    harry

    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.sh
    1
    2
    3
    4
    5
    6

    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:

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

     

    $ x="This is my test string."

    $ echo ${x#* }

     

    is my test string.

     

                        

                       

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

     

    $ x="This is my test string."

    $ echo ${x##* }

     

    string.

     

                          

                       

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

     

    $ x="This is my test string."

    $ echo ${x% *}

     

    This is my test

     

                            

                       

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

     

    $ x="This is my test string."

    $ echo ${x%% *}

     

    This

     

                              

                       

    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 |

    Share  This Page

     

    展开全文
  • 学习Bash shell编程资料推荐

    千次阅读 2014-10-18 19:48:25
    我一直觉得写好Bash ...在这篇文章,我把自己认为一些比较好的Bash shell编程资料分享出来,希望可以给大家一点帮助。 我个人看过的最好的Bash shell编程入门资料是《Linux程序设计》的第二章:shell程序设计,看

    我一直觉得写好Bash shell脚本是一件很cool的事,短短几行代码,就能完成其它编程语言几十行甚至上百行代码才能完成的功能,可惜我自己写Bash shell脚本能力实在不敢恭维。在这篇文章,我把自己认为一些比较好的Bash shell编程资料分享出来,希望可以给大家一点帮助。

    我个人看过的最好的Bash shell编程入门资料是《Linux程序设计》的第二章:shell程序设计,看这一章的同时自己动手实践,我觉得入门基本没问题了。

    入门之后,我建议大家一定要看CU论坛上shell大牛网中人经典的《shell十三问》系列文章,这些文章把很多shell编程tricky的东西讲的很细,很明白。我每次读都有新的收获。

    关于如何调试shell程序,推荐coolshell上的文章:如何调试bash脚本,在我这篇文章结尾提到的bashdb调试器,我这几天还用了一下。虽然比起gdb还差了很远(比如没有命令自动补全功能,等等),但总体感觉还可以,可以提高调试效率。

    最后推荐两个网站: 
    http://www.shellcheck.net/:用来检测shell脚本,帮你发现问题。 
    http://explainshell.com/:用来帮你理解shell脚本。

    好了,动手实践吧。Happy bashing! Happy hacking!

    展开全文
  • Linux Bash Shell编程(八):条件判断语句与示例   上一节中,我们了解了字符串截取和处理的相关命令,可以对命令的输出数据流进行筛选截取。本节开始,就到了Bash Shell编程最关键的部分:条件判断和流程控制...

    Linux Bash Shell编程(八):条件判断语句与示例

      上一节中,我们了解了字符串截取和处理的相关命令,可以对命令的输出数据流进行筛选截取。本节开始,就到了Bash Shell编程最关键的部分:条件判断和流程控制语句。本节中,我们先熟悉条件判断的各种类型、形式。

    Bash 8

    条件判断的基本语法

      条件判断的基本语法主要有两种:基于命令行的test命令和更适合于嵌入流程控制语句的条件样式。

    1. test 命令
        test命令以命令行的形式运行条件判断语句,不会有任何标准输出,该语句的执行结果被保存在预定义变量$?中(注意,$?值类似于程序返回值,而不是布尔型数据,$? 0为真,1为假),可以直接用echo命令查看,也可被多命令逻辑关系符调用,更符合使用者的习惯,但在Shell脚本中使用不便,一般不建议在Shell中使用
    test 条件判断语句
    #为了观察实际效果,一般使用echo命令查看$?预定义变量
    echo $?
    #0为真,1为假
    
    #例如:(判断语句的具体分类在下面讲到)
    test -e Hello_World.sh
    echo $?
    
    1. []包含的条件样式

        用[]包含的条件判断表达式功能与test命令相同,不采用命令式结构,可以方便地嵌入流程控制语句中作为条件,返回值同样在预定义变量$?中,除了形式不同,其余与test命令完全相同

      注意:[ ]内侧两边必须有空格,否则命令执行报错

    [ 条件判断语句 ]
    #同样使用echo命令查看条件判断语句结果
    echo $?
       
    #例如:(判断语句的具体分类在下面讲到)
    [ -e Hello_World.sh ]
    echo $?
    

    条件判断语句类型

    按照文件类型判断

    在选项后加文件名,可以判断文件(若存在)类型是否符合条件,若文件不存在直接返回假,符合条件返回真,具体文件类型判断符与ls命令结果中文件属性第一位相似

    [选项 文件名]
    #echo #?
    
    选项 作用
    -b 判断文件(若存在 (下同))是否为块设备文件(是为真 (下同))
    -c 判断文件是否为字符设备文件
    -d 判断文件是否为目录文件
    -e exist 仅判断文件是否存在
    -f file 判断文件是否为普通文件
    -L 判断文件是否为符号链接文件
    -p 判断文件是否为管道文件
    -s 判断文件是否非空(非空为真)
    -S 判断文件是否为套接字文件

    按照文件权限判断

    同样要在选项后加文件名,有权限为真,无权限或文件不存在为假。(判断的是当前用户对这个文件的权限)

    选项 作用
    -r 判断对该文件是否有读权限
    -w 判断对该文件是否有写权限
    -x 判断对该文件是否有执行权限
    -u 判断对该文件是否有SUID权限
    -g 判断对该文件/目录是否有SGID权限
    -k 判断对该目录是否有SBIT权限

    比较两个文件的信息

    格式:文件1 [选项] 文件2

    选项 作用
    -nt newer than判断文件1的最后修改时间是否比文件2晚,晚为真(0)
    -ot older than 判断文件1的最后修改时间是否比文件2早,早为真(0)
    -ef 判断两个文件的Inode号是否一致,近似为两个文件是否相同
    • 其中,Inode号是标识文件的序号,两个不同的文件可以名称相同,但Inode号不能相同,若两个文件为硬链接(保存为副本、同步更新)关系,则两文件的Inode号才会相同,其余不同
    • 两个硬链接的文件,除了Inode号相同外没有任何标志,可以使用这个判断方式判断硬链接

    比较两个整数

    若为两个变量,不需要声明为整型格式,语法:整数1 [选项] 整数2

    选项 作用
    -eq equal 判断两个整数是否相等
    -ne not equal 判断两个整数是否不等
    -gt greater than判断整数1是否大于整数2
    -lt less than 判断整数1是否小于整数2
    -ge greater/equal 判断整数1是否大于等于整数2
    -le less/equal 判断整数1是否小于等于整数2

    判断字符串相关

    语法包含在选项中,注意:两个字符串比较相关的判断符两边都要加空格,否则无论如何,返回值均为真

    选项 作用
    -z 字符串 判断字符串是否为空
    -n 字符串 判断字符串是否非空
    字符串1 == 字符串2 判断两个字符串是否相等
    字符串1 != 字符串2 判断两个字符串是否不等
    • 当字符串是变量时,如果变量没有定义,则同样视作空字符串

    两个判断条件的逻辑关系

    同时使用两个判断条件时,要注意它们之间的逻辑关系,两个判断条件的格式:条件1 [选项] 条件2

    选项 作用
    -a 逻辑与,两个条件都成立才成立
    -o 逻辑或,两个条件有一个成立就成立
    ! [条件] 逻辑非,使判断结果取反(注意,!与条件之间有空格

    条件判断语句与多命令逻辑符连用

      关于多命令顺序与逻辑符,请参阅Linux Bash Shell编程(三):重定向、多命令顺序、通配符、特殊符号

      实际上,多命令顺序与逻辑符判断前一个命令是否执行的方式就是判断预定义变量$?的值是否为0,所以可以直接将条件判断语句看作一个命令加入多命令顺序语句中,条件判断为真相当于正确执行了上一个语句。


    示例

    示例1,判断文件是否存在:

    [ -e ./test.sh ] && echo "File exists" || echo "File not found"
    #条件判断语句方括号内侧必须有空格
    #该命令执行,若文件存在,显示"File exists";否则显示"File not found"
    

    示例2,用多命令逻辑符构建单行比大小程序:

    #以下为test5.sh中的内容
    #!/bin/bash
    
    #Author:Zheng
    
    read -p "a= " a
    read -p "b= " b #通过键盘读入a,b数据,请参阅(四)
    [ $a -lt $b ] && echo "a<b" || echo "a>=b"
    

    示例3,多条件判断语句:判断输入变量是否为空并且是否值小于10

    #以下为test6.sh中内容
    #!/bin/bash
    
    #Author: Zheng
    
    read -p "Input a: " a
    #若a非空且小于10,则输出Yes
    [ -n $a -a $a -lt 10 ] && echo "Yes" || echo "No"
    #此脚本中未加入判断a是否为整数的条件,留待改进
    

    索引

    下一节,Linux Bash Shell编程(九):流程控制语句(上) 分支语句(if、case),我们将学习Bash流程控制语句

    上一节,Linux Bash Shell编程(七):字符串截取与处理(cut、printf、awk、sed)

    展开全文
  • 一张图带你掌握bash shell编程。PDF版本下载请在公众号后台回复:【Shell】即可。推荐阅读推荐一款在线 Nginx 配置生成器推荐十款Linux网络监视工具W...
  • Linux Bash Shell编程(一):Shell概述与Hello World实现 Shell 概述   Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止并...
  • Linux Bash Shell编程(二):Bash基本功能(历史、补全、别名、快捷键)   上一节简单介绍了Linux Shell并用echo命令编写了第一个Bash脚本Hello World。本节我们来认识一下熟悉的Bash命令解释器的基本功能:命令...
  • Linux Bash Shell编程(四):变量(上) 变量分类与相关操作 上一节,我们了解了Bash中的重定向以及特殊符号,从本节开始我们来一起探索Bash中变量的奥秘。本节我们先来了解下Bash中变量的基本知识以及对变量处理的...
  • Bash Shell编程基础

    千次阅读 2018-03-18 17:42:37
    转载请注明出处:...2)在Unix历史中,Shell作为系统的命令行调用接口,以独立的程序实现。3)早期的Shell提供了一些基本特性,供用户使用。功能逐渐完善,发展...
  • Bash SHELL 中文文档,最权威的中文文档,这个文档是pdf的,做的很精致, 是官方bash指南的中文版,非扫描版. 使用及其方便,是学习linux bash的必备工具书。
  • Linux Bash Shell编程(三):重定向、多命令顺序、通配符、特殊符号   上一节我们学习了Bash中的基本功能,相信经过前两节的学习,大家平时使用Bash的效率得到了一点提高。本节,我们将继续探索Bash特性,了解...
  • Linux Bash Shell编程(九):流程控制语句(上) 分支语句(if、case)   上一节中,我们学习了Bash中各种类型的条件判断语句。在Bash中,流程控制是条件判断语句的最终目的,条件判断语句是流程设计的基础条件...
  • Linux Bash Shell编程(十):流程控制语句(下) 循环语句(for while until) 上一节中,我们学习了流程控制语句中的分支语句。本节,我们一起来了解一下流程控制中的最后一个部分——循环语句,学会运用三个常见...
  • Linux Bash Shell编程(七):字符串截取与处理(cut、printf、awk、sed、sort)含示例   上一节中,我们了解了正则表达式的基本作用及其用法。本节我们来研究字符串截取、格式化输出、字符串处理命令 cut 命令...
  • Linux Bash Shell编程(五):变量(下)变量运算、内容替换、环境变量配置文件 上一节,我们对变量有了初步的了解,学会了变量的分类以及各种变量的基本操作和作用。本节我们来了解以下变量运算和运算符、变量测试...
  •   上一节中,我们了解了Bash Shell中的变量计算、变量内容替换和环境变量配置文件相关内容。在了解了变量及其相关运算/操作后,本节开始,我们将一起了解Shell中的字符串处理方面内容,由于Bash的部分命令支持正则...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,111
精华内容 27,244
关键字:

bashshell编程