Bash example, Part 1

By learning how to use bash scripting language programming, Linux will make the daily interaction more interesting and productive, but also can take advantage of those already know and love the standard UNIX concepts (such as pipes and redirection). In this three-part series, Daniel Robbins will be an example to guide you how to use bash programming. He will talk about very basic knowledge (which makes this series is very suitable for beginners), and gradually introduce more advanced features in subsequent series.

You may want to ask: Why learn Bash programming? Well, here are a few compelling reasons:

It has been in operation

If you look, you may find that: You are running bash. Because bash is the standard Linux shell, and used for various purposes, so even if you change the default shell, bash may still run somewhere in the system. Because bash is already running, any bash script to run later are inherently efficient use of memory, because they share memory with any bash process has been running. If the tool is running to handle the job, and do it well, why should I load a 500K interpreter?





Back to top


Already using it

Not only in the running bash, in fact, you are still dealing with every day bash. It is always there, so learning how to maximize the use of it makes sense. Doing so will make your bash experience more fun and productive. But why should learn bash programming ? Simply because you are already considering how to run the command, CPing files, and pipeline and redirect the output. Why not learn a language to use and when to use the concept of those provinces have strong know and love? UNIX command shell unlock the potential of the system, and bash is precisely the Linux shell. It is a senior bond between you and the machine. Increase knowledge bash it, it will automatically increase your productivity under Linux and UNIX - just that simple.





Back to top


Bash confusion

Learning bash the wrong way and confusing. Many novices enter "man bash" to view the bash help pages, but only got a very simple and technical description of shell functionality. Others enter "info bash" (to view the GNU info documentation), can only help re-display the page, or (if you're lucky) slightly more friendly info documentation.

While this may cause some disappointment for beginners, but the standard bash documentation can not meet all the requirements, it is only suitable for those who are already familiar with shell programming in general. Help page does have a lot of excellent technical information but to help beginners are limited.

This is the purpose of this series lies. In this series, I will describe how to actually use bash programming concepts in order to write your own scripts. And description of the different techniques, I will explain to you in simple language so that you not only know what to do, should also know when to use. At the end of this three-part series, you can write your own intricate bash scripts, and can freely use the bash as well as to supplement the knowledge through reading (and understanding) the standard bash documentation. let's start.





Back to top


Environment Variables

Bash and almost all the other shell, the user can define the environment variable, these environment variables to be stored in ASCII strings. The most convenient place in that environment variables: they are a standard part of UNIX process model. This means: not only the environment variables used by the shell script alone, but also can be used by standard compiled programs. When bash the "Export" environment variable, run any program in the future, whether it is not a shell script, you can read the settings. A good example is the vipw command, which normally allows root user to edit the system password file. By EDITOR environment variable to the name of your favorite text editor, you can configure vipw, so use the editor instead of vi, if used xemacs and really do not like vi, so it is very convenient.

In bash, the standard way to define environment variables are:

$ myvar='This is my environment variable!'

This defines the environment variable called "myvar" and contains the string "This is my environment variable!". There are more than a few notes: First, the equal sign "=" on both sides there is no space, any space will result in an error (try it and see). The second thing to notice is that: although the definition of a word in quotation marks can be omitted, but when the environmental variable value is defined more than one word (or tab key spaces), quotes are necessary.

Reference details

For information about how to use quotes in bash very detailed information, see the bash page in the "References" section. Special character sequence "extensions" of other values ​​(replacing) the process does bash string becomes complicated. This series will only address the most commonly cited features.

Third, although generally single quotes may be replaced by double quotation marks, but in the embodiment, this can cause an error. why? Because using single quotes disables a bash called extension properties, where special characters and characters replaced by the value of the series. For example, "!" Character is the history expansion character, bash normally replace it with a previously entered commands. (This series of articles about the history will not expand, because it is not commonly used in bash programming. For more information about the history of the expansion, see the bash page "history expansion" one.) While this macro function is very convenient, but right now we want to add a simple environment variables behind the exclamation point, rather than macro.

Now, let's look at how to actually use environment variables. Here's an example:

$ echo $myvar
This is my environment variable!

By adding in front of the environment variable $ a, bash can replace it with the value of myvar. This is called "variable expansion" in bash terminology. However, doing so will how:

$ echo foo$myvarbar
foo

We hope echo "fooThis is my environment variable! Bar", but it is not the case. What is wrong? Simply put, bash variable expansion facility fell into confusion. It does not recognize what a variable to be expanded: $ m, $ my, $ myvar, $ myvarbar and so on. How more clearly described clearly tell bash what a variable reference? Try this:

$ echo foo${myvar}bar
fooThis is my environment variable!bar

As you can see, when the environment variable is not obvious from the surrounding text, you can use curly braces to enclose it. While $ myvar can type faster, and work correctly in most cases, but $ {myvar} was able in almost all cases the correct syntax analysis. In addition, both the same, the two forms of variable expansion seen in the rest of the series. Remember: When the environment variable is not from the surrounding text by whitespace (space or tab key), use the more explicit curly braces.

Recall that we can also mention the "Export" variables. When exporting an environment variable, which can be automatically used by any script or executable environment to run later. shell script can use the shell's built-in support for environment variables "to" environment variable, while C programs can use the getenv () function call. Here are some C code examples, input and compile them - it will help us to understand environment variables from the perspective of C:


myvar.c - sample environment variable C program

#include <stdio.h>
#include <stdlib.h>
int main(void) {
  char *myenvvar=getenv("EDITOR");
  printf("The editor environment variable is set to %s\n",myenvvar);
}

Save the above code into a file myenv.c, and then issue the following command to compile:

$ gcc myenv.c -o myenv

Now, the directory will be an executable program, it will print the value at runtime EDITOR environment variable (if the value of words). This is the case of running on my machine when:

$ ./myenv
The editor environment variable is set to (null)

Ah ... because there is no EDITOR environment variable to any value, so the program C to give an empty string. Let's try to set it to a specific value:

$ EDITOR=xemacs
$ ./myenv
The editor environment variable is set to (null)

Although myenv want to print the value "xemacs", but because there is no export environment variables, so it did not work very well. This time it works correctly:

$ export EDITOR
$ ./myenv
The editor environment variable is set to xemacs

Now, as your eyes can see: do not export environment variables, another process (C program is an example in this case) can not see the environment variable. Incidentally, if desired, can be defined in a row and export the environment variable as follows:

$ export EDITOR=xemacs

This is the same two-line version of the effect. Now that demonstrates how to use unset to remove the environment variables:

$ unset EDITOR
$ ./myenv
The editor environment variable is set to (null)

dirname 和 basename

Note: The file or directory dirname and basename not on the disk, they are just string manipulation commands.





Back to top


Truncate strings Overview

Truncated string is truncated to the original character string into smaller independent blocks, it is one of the tasks of daily general shell script. Many times, shell scripts need to take a fully qualified path, and find the file or directory ends. While it is possible to achieve (and fun) code this in bash, the standard basename UNIX executable program can accomplish this great work:

$ basename /usr/local/share/doc/foo/foo.txt
foo.txt
$ basename /usr/home/drobbins
drobbins

Basename is a very simple tool truncates the string. Dirname its associated command returns "other" part of the path basename discarded.

$ dirname /usr/local/share/doc/foo/foo.txt
/usr/local/share/doc/foo
$ dirname /usr/home/drobbins/
/usr/home





回页首


命令替换

需要知道一个简便操作:如何创建一个包含可执行命令结果的环境变量。这很容易:

$ MYDIR=`dirname /usr/local/share/doc/foo/foo.txt`
$ echo $MYDIR
/usr/local/share/doc/foo

上面所做的称为“命令替换”。此例中有几点需要指出。在第一行,简单地将要执行的命令以 反引号 括起。那不是标准的单引号,而是键盘中通常位于 Tab 键之上的单引号。可以用 bash 备用命令替换语法来做同样的事:

$ MYDIR=$(dirname /usr/local/share/doc/foo/foo.txt)
$ echo $MYDIR
/usr/local/share/doc/foo

如您所见,bash 提供多种方法来执行完全一样的操作。使用命令替换可以将任何命令或命令管道放在 ` ` 或 $( ) 之间,并将其分配给环境变量。真方便!下面是一个例子,演示如何在命令替换中使用管道:

MYFILES=$(ls /etc | grep pa)
bash-2.03$ echo $MYFILES
pam.d passwd





回页首


象专业人员那样截断字符串

尽管 basename 和 dirname 是很好的工具,但有时可能需要执行更高级的字符串“截断”,而不只是标准的路径名操作。当需要更强的说服力时,可以利用 bash 内置的变量扩展功能。已经使用了类似于 ${MYVAR} 的标准类型的变量扩展。但是 bash 自身也可以执行一些便利的字符串截断。看一下这些例子:

$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg

在第一个例子中,输入了 ${MYVAR##*fo}。它的确切含义是什么?基本上,在 ${ } 中输入环境变量名称,两个 ##,然后是通配符 ("*fo")。然后,bash 取得 MYVAR,找到从字符串 "foodforthought.jpg" 开始处开始、且匹配通配符 "*fo" 的 最长 子字符串,然后将其从字符串的开始处截去。刚开始理解时会有些困难,为了感受一下这个特殊的 "##" 选项如何工作,让我们一步步地看看 bash 如何完成这个扩展。首先,它从 "foodforthought.jpg" 的开始处搜索与 "*fo" 通配符匹配的子字符串。以下是检查到的子字符串:

f   
fo      MATCHES *fo
foo 
food
foodf       
foodfo      MATCHES *fo
foodfor
foodfort    
foodforth
foodfortho  
foodforthou
foodforthoug
foodforthought
foodforthought.j
foodforthought.jp
foodforthought.jpg

在搜索了匹配的字符串之后,可以看到 bash 找到两个匹配。它选择最长的匹配,从初始字符串的开始处除去,然后返回结果。

上面所示的第二个变量扩展形式看起来与第一个相同,但是它只使用一个 "#" -- 并且 bash 执行 几乎 同样的过程。它查看与第一个例子相同的子字符串系列,但是 bash 从初始字符串除去 最短 的匹配,然后返回结果。所以,一查到 "fo" 子字符串,它就从字符串中除去 "fo",然后返回 "odforthought.jpg"。

这样说可能会令人十分困惑,下面以一简单方式记住这个功能。当搜索最长匹配时,使用 ##(因为 ## 比 # 长)。当搜索最短匹配时,使用 #。看,不难记吧!等一下,怎样记住应该使用 '#' 字符来从字符串开始部分除去?很简单!注意到了吗:在美国键盘上,shift-4 是 "$",它是 bash 变量扩展字符。在键盘上,紧靠 "$" 左边的是 "#"。这样,可以看到:"#" 位于 "$" 的“开始处”,因此(根据我们的记忆法),"#" 从字符串的开始处除去字符。您可能要问:如何从字符串末尾除去字符。如果猜到我们使用美国键盘上紧靠 "$" 右边 的字符 ("%),那就猜对了。这里有一些简单的例子,解释如何截去字符串的末尾部分:

$ MYFOO="chickensoup.tar.gz"
$ echo ${MYFOO%%.*}
chickensoup
$ echo ${MYFOO%.*}
chickensoup.tar

正如您所见,除了将匹配通配符从字符串末尾除去之外,% 和 %% 变量扩展选项与 # 和 ## 的工作方式相同。请注意:如果要从末尾除去特定子字符串,不必使用 "*" 字符:

MYFOOD="chickensoup"
$ echo ${MYFOOD%%soup}
chicken

在此例中,使用 "%%" 或 "%" 并不重要,因为只能有一个匹配。还要记住:如果忘记了应该使用 "#" 还是 "%",则看一下键盘上的 3、4 和 5 键,然后猜出来。

可以根据特定字符偏移和长度,使用另一种形式的变量扩展,来选择特定子字符串。试着在 bash 中输入以下行:

$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga

这种形式的字符串截断非常简便,只需用冒号分开来指定起始字符和子字符串长度。





回页首


应用字符串截断

现在我们已经学习了所有截断字符串的知识,下面写一个简单短小的 shell 脚本。我们的脚本将接受一个文件作为自变量,然后打印:该文件是否是一个 tar 文件。要确定它是否是 tar 文件,将在文件末尾查找模式 ".tar"。如下所示:


mytar.sh -- 一个简单的脚本

#!/bin/bash
if [ "${1##*.}" = "tar" ]
then 
    echo This appears to be a tarball.
else
    echo At first glance, this does not appear to be a tarball.
fi

要运行此脚本,将它输入到文件 mytar.sh 中,然后输入 "chmod 755 mytar.sh",生成可执行文件。然后,如下做一下 tar 文件试验:

$ ./mytar.sh thisfile.tar
This appears to be a tarball.
$ ./mytar.sh thatfile.gz
At first glance, this does not appear to be a tarball.

好,成功运行,但是不太实用。在使它更实用之前,先看一下上面使用的 "if" 语句。语句中使用了一个布尔表达式。在 bash 中,"=" 比较运算符检查字符串是否相等。在 bash 中,所有布尔表达式都用方括号括起。但是布尔表达式实际上测试什么?让我们看一下左边。根据前面所学的字符串截断知识,"${1##*.}" 将从环境变量 "1" 包含的字符串开始部分除去最长的 "*." 匹配,并返回结果。这将返回文件中最后一个 "." 之后的所有部分。显然,如果文件以 ".tar" 结束,结果将是 "tar",条件也为真。

您可能会想:开始处的 "1" 环境变量是什么。很简单 -- $1 是传给脚本的第一个命令行自变量,$2 是第二个,以此类推。好,已经回顾了功能,下面来初探 "if" 语句。





回页首


If 语句

与大多数语言一样,bash 有自己的条件形式。在使用时,要遵循以上格式;即,将 "if" 和 "then" 放在不同行,并使 "else" 和结束处必需的 "fi" 与它们水平对齐。这将使代码易于阅读和调试。除了 "if,else" 形式之外,还有其它形式的 "if" 语句:

if [ condition ]
then 
    action
fi

只有当 condition 为真时,该语句才执行操作,否则不执行操作,并继续执行 "fi" 之后的任何行。

if [ condition ]
then 
    action
elif [ condition2 ]
then 
    action2
.
.
.
elif [ condition3 ]
then 
else
    actionx
fi

以上 "elif" 形式将连续测试每个条件,并执行符合第一个 条件的操作。如果没有条件为真,则将执行 "else" 操作,如果有一个条件为真,则继续执行整个 "if,elif,else" 语句之后的行。





回页首


下一次

我们已经学习了最基本的 bash 功能,现在要加快脚步,准备编写一些实际脚本。在下一篇中,将讲述循环概念、函数、名称空间和其它重要主题。然后,将准备好编写一些更复杂的脚本。在第三篇中,将重点讲述一些非常复杂的脚本和功能,以及几个 bash 脚本设计选项。再见!



 

参考资料



 

关于作者

作者

Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo 项目的总设计师,Gentoo Technologies, Inc. 的 CEO,Linux Advanced Multimedia Project (LAMP) 的顾问,Macmillan 书籍 Caldera OpenLinux UnleashedSuSE Linux UnleashedSamba Unleashed 的作者。Daniel 自小学二年级起就与计算机结下不解之缘,那时他首先接触的是 Logo 程序语言,并沉溺于 Pac-Man 游戏中。 这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 的首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 一起共渡时光,他们的孩子将在今年春天诞生。可通过 [email protected] 与 Daniel Robbins 取得联系。


转载于:https://www.cnblogs.com/licheng/archive/2008/08/05/1261052.html

Guess you like

Origin blog.csdn.net/weixin_34289744/article/details/93800862