天天看点

bash常用特性之一

Bash介绍:

Bash(GNU Bourne-Again SHell)是许多Linux平台的内定Shell,事实上,还有许多传统UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等,Shell Script大致都类同,当您学会一种Shell以后,其它的Shell会很快就上手,大多数的时候,一个Shell Script通常可以在很多种Shell上使用

BASH的正确缩写:

BASH = GNU Bourne-Again SHell,BASH 是 GNU 组织开发和推广的一个项目。

BASH的作者和产生:

Bourne shell 的作者是 Steven Bourne,它是 UNIX 最初使用的 Shell 并且在每种 UNIX 上都可以使用。

而BASH 与 Bourne shell 完全向后兼容,是Bourne shell的扩展。

bash 内置特性

文件名通配:globbing

Bash本身没有正则表达式的功能,在脚本里,使用正则表达式的是命令和软件包

例如sed和awk,它们可以解释正则表达式.

Bash所做的是展开文件名扩展 -- 这就是所谓的通配(globbing) -- 但它不是使用标准的正则表达式. 而是使用通配符. 通配解释标准的通配符:*和?, 方括号括起来的字符,还有其他的一些特殊的字符(比如说^用来表示取反匹配).然而通配机制的通配符有很大的局限性. 包含有*号的字符串将不会匹配以点开头的文件,例如.bashrc. 另外,通配机制的? 字符和正则表达式中表示的意思不一样.

看图说话:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code>#在script创建了五个文件</code>

<code>[root@localhost script]</code><code># touch a.1 b.c c.c t2.sh test.txt</code>

<code>[root@localhost script]</code><code># ls</code>

<code>a.1  b.c  c.c  </code><code>fdisk</code><code>.sh  </code><code>local</code><code>.sh  t2.sh  </code><code>test</code><code>.txt  tss.sh</code>

<code>[root@localhost script]</code><code># ls -l</code>

<code>total 12</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 a.1</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 b.c</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 c.c</code>

<code>-rw-r--r--. 1 root root 3126 Feb 22 00:44 </code><code>fdisk</code><code>.sh</code>

<code>-rw-r--r--. 1 root root   28 Feb 22 07:25 </code><code>local</code><code>.sh</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 t2.sh</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 </code><code>test</code><code>.txt</code>

<code>-rw-r--r--. 1 root root   10 Feb 22 01:39 tss.sh</code>

<code>#查看一下script以t开头的中间跟任一字符,以.sh结尾的文件</code>

<code>[root@localhost script]</code><code># ls -l t?.sh</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 t2.sh</code>

15

16

17

18

19

<code>#查看以[ab]任意一个字母开头的文件</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:30 abc.ddl</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:31 anb.ppt</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:30 cvb.doc</code>

<code>[root@localhost script]</code><code># ls -l [ab]*</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 a.1</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:30 abc.ddl</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:31 anb.ppt</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 b.c</code>

<code>#非字母a或b开头的文件</code>

<code>[root@localhost script]</code><code># ls -l [^ab]*</code>

<code>[root@localhost script]</code><code># ls -l {b*,c*,*st*}</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 c.c</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:30 cvb.doc</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 </code><code>test</code><code>.txt</code>

注:Bash会对命令行中没有引号引起来的字符尝试文件名扩展

<code>[root@localhost script]</code><code># echo *</code>

<code>a.1 abc.ddl anb.ppt b.c c.c cvb.doc </code><code>fdisk</code><code>.sh </code><code>local</code><code>.sh t2.sh </code><code>test</code><code>.txt tss.sh</code>

文件名扩展能匹配点开头的文件,但仅在模式字串明确地包含字面意思的点(.)时才扩展.

<code>[root@localhost ~]</code><code># ls -a .bash_*</code>

<code>.bash_history  .bash_logout  .bash_profile</code>

<code>[root@localhost ~]</code><code># ls -al [?]bash_*</code>

<code>ls</code><code>: cannot access [?]bash_*: No such </code><code>file</code> <code>or directory</code>

<code>[root@localhost ~]</code><code># ls -al [.]bash_*</code>

<code>ls</code><code>: cannot access [.]bash_*: No such </code><code>file</code> <code>or directory</code>

这样还是可以的

<code>[root@localhost ~]</code><code># ls -al .[b]?sh_profile</code>

<code>-rw-r--r--. 1 root root 176 May 20  2009 .bash_profile</code>

<code>[root@localhost ~]</code><code># ls -al .[b]?shr*</code>

<code>-rw-r--r--. 1 root root 176 Sep 22  2004 .bashrc</code>

可以改变Bash对通配字符进行解释的行为.

set -f 命令或set -o noglob可以禁止通配机制, 并且shopt的选项nocaseglob和nullglob 能改变通配的行为.

<code>[root@localhost script]</code><code># ls a*</code>

<code>a.1  abc.ddl  anb.ppt</code>

<code>[root@localhost script]</code><code># set -f</code>

<code>ls</code><code>: cannot access a*: No such </code><code>file</code> <code>or directory</code>

这时表明通配功能己经关闭,如果要开启,可以使用

set +o noglob

命令补全、路径补全

Bash中的命令分为两种,一种是bash自带的内部命令,一种是通过环境变量读取的可执行文件,这个变量就是PATH,以冒号间隔的多个路径,命令补全则是通过PATH的多路径查找到可执行的文件所在位置

为了简化打字工作,bash shell 提供了几种可以对输入不完整的文本进行自动补全的方法,如果想对输入进行补全,只需输入初始的几个字符,然后按“Tab”键,系统会自动匹配所需要的其余输入,当有多种匹配时,系统会结出提示,按"ESC+?"组合键或按两次"Tab"键,可以列出所有可能的匹配,自动补全可以应用于下面的4类输入工作之中。

环境变量名补全

<a href="http://s3.51cto.com/wyfs02/M01/18/BD/wKiom1MTEbrABCwCAADIOExJYDs838.jpg" target="_blank"></a>

如果输入的文本以"$"开始,shell就以当前shell的环境变量补全文本

用户名补全

如果输入的文本以“~”开始,shell会以用户名补全文本。

命令、别名或函数的名字补全

如果文本以常规字符开始,shell将利用命令、别名或函数名来补全文本

主机名补全

如果输入的文本以“@”符号开始,系统会利用/etc/hosts文件中的主机名来补全文本

<a href="http://s3.51cto.com/wyfs02/M02/18/BE/wKiom1MTEnXx9jJcAAEswoUdECs984.jpg" target="_blank"></a>

自动补全快捷键(此快捷键在远程终端无法使用)

Alt+~  以一个用户名补全此处文本

Alt+$ 用变量补全此处的文本

Alt+@以一个主机名补全此处文本

路径补全

而路径补全是在给出打头路补全,如果没有打头的路径,则视为以当前路径开始补全。

命令历史

Bash可以保存过去曾经执行过的命令列表(即history 命令产生的列表),当前shell进程引用过的命令都会保存在缓冲区中,如果有退出操作时,缓冲区中的命令会在shell退出时将以前运行过的命令保存至文件中(即用户家目录下的.bash_histor)

history 快捷方式:

!#:为命令历史列表中的命令编号,可用执行第#条命令

!!:执行上一命令;

!- #:执行命令历史列表中的倒数第#命令;

!string :执行命令历史列表中的最近一次以string开头的命令;

<code>[root@localhost etc]</code><code># echo "$PATH"</code>

<code>/usr/lib64/qt-3</code><code>.3</code><code>/bin</code><code>:</code><code>/usr/local/sbin</code><code>:</code><code>/usr/local/bin</code><code>:</code><code>/sbin</code><code>:</code><code>/bin</code><code>:</code><code>/usr/sbin</code><code>:</code><code>/usr/bin</code><code>:</code><code>/usr/local/axel/bin</code><code>:</code><code>/usr/local/nginx/sbin</code><code>:</code><code>/root/bin</code><code>:</code><code>/usr/local/apache/bin</code><code>:</code><code>/usr/local/apache/bin</code><code>:</code><code>/usr/local/axel/bin</code><code>:</code><code>/usr/local/nginx/sbin</code>

<code>[root@localhost etc]</code><code># !e</code>

<code>echo</code> <code>"$PATH"</code>

!$:引用上一个命令的最后一个参数;(也可以使用按下esc,之后按一下.)

history

-c: 清空列表

<code>[root@localhost etc]</code><code># history  |tail -5</code>

<code>  </code><code>119  </code><code>history</code> <code>-d 199</code>

<code>  </code><code>120  </code><code>history</code> <code>-d 119</code>

<code>  </code><code>121  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>  </code><code>122  </code><code>history</code> <code>-d 118</code>

<code>  </code><code>123  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>[root@localhost etc]</code><code># history -c</code>

<code>[root@localhost etc]</code><code># history</code>

<code>    </code><code>1  </code><code>history</code>

-d #: 删除指定的历史命令

<code>  </code><code>118  </code><code>history</code>

<code>  </code><code>119  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>  </code><code>120  </code><code>history</code> <code>-d 199</code>

<code>  </code><code>121  </code><code>history</code> <code>-d 119</code>

<code>  </code><code>122  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>[root@localhost etc]</code><code># history -d 118</code>

-a: 追加当前会话的命令历史至历史文件中去;

命令历史相关的环境变量:

HISTSIZE:命令历史中可以保存的命令的个数;( echo $HISTSIZE,默认1000条)

HISTFILE: 命令历史文件;(echo $HISTFILE,用户的历史文件存放的位置)

HISTFILESIZE:命令历史文件可以保存的命令的个数;(echo "$HISTFILESIZE"默认1000条)

HISTCONTROL: 控制命令历史的生成;

ignoredups: 忽略记录重复的命令;连续的相同命令才为重复;

<code>[root@localhost ~]</code><code># echo "$HISTCONTROL"</code>

<code>ignoredups</code>

<code>[root@localhost ~]</code><code># history |tail -5</code>

<code>   </code><code>15  </code><code>echo</code> <code>"$HISTCONTRAL"</code>

<code>   </code><code>16  </code><code>echo</code> <code>"$HISTCONTROL"</code>

<code>   </code><code>17  </code><code>history</code>

<code>   </code><code>18  </code><code>echo</code> <code>"$HISTCONTROL"</code>

<code>   </code><code>19  </code><code>history</code> <code>|</code><code>tail</code> <code>-5</code>

ignorespace: 不记录以空白字符开头的命令;

<code>[root@localhost ~]</code><code>#  history |tail -5</code>

<code>   </code><code>31  </code><code>history</code>

<code>   </code><code>32   </code><code>echo</code> <code>"$HISTCONTROL"</code>

<code>   </code><code>33  HISTCONTROL=ignorespace</code>

<code>   </code><code>34  </code><code>ls</code> <code>/var</code>

<code>   </code><code>35  </code><code>history</code>

<code>[root@localhost ~]</code><code>#  ls /</code>

<code>bin   etc   lib64       misc  opt   sbin     sys  var</code>

<code>boot  home  lost+found  mnt   proc  selinux  tmp</code>

<code>dev   lib   media       net   root  srv      usr</code>

<code>[root@localhost ~]</code><code>#   history |tail -5</code>

ignoreboth: 同时具有上面两种特性;

命令行编辑(快捷键)

ctrl+a:光标移动到行首

ctrl+e:光标移动到行尾

ctrl+u:清除光标前至行首的所有内容

ctrl+k:清除光标后至行尾的内容

ctrl+l:清屏

Ctrl+f光标向后移动一个字符

ctrl+b:光标向前移动一个字符

ctrl+h:删除光标前的一个字符

ctrl+d:从当前shell登出(和exit很像) "EOF"(文件结束符)

ctrl+i:就是一个tab键

ctrl+j:新行

ctrl+m:回车

esc b:左移一个单词

esc f:右移一个单词

输入、输出重定向、管道

在linux系统中,数据流可分为3类:数据输入,数据输出和错误输出,相对的,每一个进程也都有3个特殊的文件描述:标准输入(stdin,文件描述指针为0),标准输出(stdout,文件描述指针为1)和标准错误输出(stderr,文件描述指针为2),这3个特殊文件描述指针使进程在通常情况下接收标准输入设备的输入,由标准输出设备显示输出.

而在输入通常指传给一个命令的键盘输入。通常标准输出是被定向到显示器,如果在执行过程中发生错误,可能会发生错误,可能会存在一条错误消息,这是标准错误数据流,通常也会被定向到显示器。有两种基本的方法可以用来重定向标准输入(stdin)、标准输出和标准错误(stderr),可以利用管道把这些数据流之一输送组另一个命令,也可以利用I/O重定向把这些数据流之一重定向一个文件.所谓管道是指将某一个命令的输出结果传送到另一个命令,当成另一外命令的输入,其代表符号是"|".所谓I/O重定向是指命令执行的结果重新导出到其他设备或文件(以"&gt;"或“&gt;&gt;”来表示)或是重新导入到其他设备或文件(以"&lt;"或"&lt;&lt;"来表示)

分类:

输入重定向:&lt;, &lt;&lt;

&lt;: 输入重定向

&lt;&lt; EOF: 此处创建文件, Here Document

常用于在脚本中创建文件或生成菜单;

<code>[root@localhost script]</code><code># cat  echo.sh</code>

<code>cat</code> <code>&lt;&lt;EOF</code>

<code>   </code><code>cpu) print cpu  information</code>

<code>   </code><code>mem) print memory information</code>

<code>   </code><code>disk) print disk information</code>

<code>   </code><code>quit) quit</code>

<code>EOF</code>

<code>[root@localhost script]</code><code># bash echo.sh</code>

输出重定向:&gt;, &gt;&gt;

&gt;: 覆盖输出

<a href="http://s3.51cto.com/wyfs02/M02/18/D8/wKioL1MTKB2grzYZAAJzU8gwCcM024.jpg" target="_blank"></a>

&gt;&gt;: 追加输出

set -C:禁止使用覆盖重定向至已经存在的文件;

set +C: 关闭上述特性;

&gt;|:在-C特性下,强制使用覆盖重定向;

错误重定向:2&gt;, 2&gt;&gt;

2&gt;: 覆盖

将错误的信息输出到指定的文本中(会覆盖原文本的内容)

2&gt;&gt;: 追加

将错误输出到文本的的最后一行(不会覆盖原文本的内容)

<a href="http://s3.51cto.com/wyfs02/M01/18/DC/wKiom1MTLDaBqUP6AACK5BSVcm8103.jpg" target="_blank"></a>

<a href="http://s3.51cto.com/wyfs02/M00/18/DC/wKiom1MTLEqjhq_NAAEB6Rvp_8Q477.jpg" target="_blank"></a>

管道

在linux系统中,管道的主要功能是将其他程序的输出结果直接导出到另一个程序作为输入数据,即将前一个程序的输出作为后一个程序的输入

<a href="http://s3.51cto.com/wyfs02/M01/18/DF/wKioL1MTLlCDj6N7AABNoievvO0837.jpg" target="_blank"></a>

并不是所有的命令都可以用管道接收

<code>#pwd</code>

<code>/var/log</code>

<code>#ls /var/log | file</code>

此命令将无法执行。(由于file在此时引用的是相对路径,如果想正确使用必须要使用如下方法)                

<code>#file `ls /var/log`|cut -d: -f2 |tr -d ' '|sort|uniq</code>

(查看var/log下的文件类型,并取出第二段,除去前端的空格,排序,并去掉重复的.)

tee:

将第一个命令的结果保存到文件并同时输出到显示器。

<code>#ls /etc |tee /tmp/etc.out |tr 'a-z' 'A-Z'|tr -d '0-9'</code>

此命令就是将/etc下的所有目录或文件,全输出到/tmp/etc.out并在显示器显示时,去掉'0-9'的数字(/tmp/etc.out中的数据并不会因此而发生变化。)

命令别名

alias, 假名,别名,bash的一个内建命令,用来给常用的较长的命令定义个简短的名称。

alias命令的基本格式为alias [word[='command']], []内为可选项。定义word为command的别名。若=’command’部分省略,则输出word之前的定义,未定义则报错。单独的alias列出当前环境中所有可用的别名。通常来讲,关于alias,知道这么多就行了。但在使用alias的过程中还有一些问题需要注意。

如果bash的expand_aliases选项没有被设置,那么在非交互式shell中alias不会被执行展开。也就是说,在shell脚本中,使用alias会导致”command not found”的错误。使用shopt命令来设置expand_aliases选项:

<code>#设置别名扩展(启用别名)</code>

<code>#shopt -s expand_aliases</code>

=======================================第一部份========================================

本文转自 jinlinger 51CTO博客,原文链接:http://blog.51cto.com/essun/1365977,如需转载请自行联系原作者