首页 > 代码库 > Bash

Bash

在linux系统中SHELL是一个很重要的东西,它是用户对系统进行操作的接口,它为用户提供简单一用的操作界面,常见的SHELL大概有以下几种(使用cat /etc/shells查看):

       Sh:由BELL实验室开发,全名为:Bourne Shell

       Tcsh:由Bill Joy开发,全名为:C shell(csh),后经升级变为tcsh

       Ksh:由david korn开发,全名为:korn shell

       Bash:由GUN组织开发,全名为:Bourne Again shell,(Bourne shell的扩展,因为其开源,由开源社区维护,被作为默认SHELL

       Zsh:(z是英文字母最后一个,取义最强)默认系统中所支持的最好的SHELL

接下来说一说bash的一些特性,bash作为linux的默认SHELL,它的功能还是很强大的,在使用上为我们提供了很大的方便,首先的一点就是它可以让我们自定义一个命令或者字符串的别名。

  • 命令的别名(alias命令查看已经定义好的别名)

这个命令的好处就在于当一个命令或者字符串总是需要重复输入或者更换另一种输入方式的时候能够简便一些(加上\命令使用原始命令,例如:\ls=ls,而直接输入的ls= ls --color=auto)。

定义的方法是:alias 自己的命名“原来的命令”

例如:alias cls‘clear’:当输入这个命令之后,使用cls也可以实现清屏的功能

但是请注意使用这个命令进行的更换别名的操作只能在当前的SHELL才有用,就是说当你重启SHELL之后,都会被还原。对于每个用户来说,都有一个私有的bash配置文件,用于保存别名,这个文件是~/.bashrc,如果修改了这个文件里的内容那么就能够长久的修改alias,即使重启shell仍然生效,但也是需要重启才能生效(也可以使用.=source命令替代重启,用法:“.= ~/.bashrc”,功能是加载脚本到内存),所以如果要添加一个别名,那么使用命令和修改文件这两种方式要同时使用才能够不管重启与否都能使用。当然别名也可以撤销,使用命令建立的别名,使用“unalias 别名的名称“即可撤销。

二、命令历史:

BASH进程会保存其会话中用户曾经执行过的命令,以方便用户重复执行某个命令,如果想执行上一个执行过的命令,可以有以下四种方法:

1.使用上方向键,回车执行

2.ctrl+p(等同于上方向键)

3.!-1:把之前执行过的命令再执行一遍

4.!!:重复执行前一个命令

不过,当已经输入的命令特别多的时候在使用上头的方法就有点不方便了,那么此时就可以使用“history”命令查看所有的历史命令(这些命令都会暂时的保存在内存中,断电就会丢失,要想长久的保存,可以修改“~/.bash_history”文件,登陆shell的时候,BASH会自动读取~/.bash_history文件中所记录的所有命令)。在使用这个命令的时候有两个选项:

-d 9:删除第九条历史记录(具体内容查看帮助)

-c:清空历史缓冲区中的历史记录

在使用了这个命令之后会打印出所有的历史命令,可以使用与历史相关的bash变量来控制输出的内容和格式,常见的四个变量如下(使用echo $变量可以查看):

       HISTSIZE: 保存的历史命令的数量上限(默认值--1000)(当数量达到设定值后,编号继续增加,丢弃最老的历史)

       HISTFILESIZE: 保存历史命令的文件的大小,和HISTSIZE几乎一样

       HISTTIMEFOMAT:设置输出的格式,比如需要打印出每个历史命令使用的时间就可以使用这个命令: HISTTIMEFOMAT="%F %T "

       HISTCONTROL:命令的记录方式(什么记录,什么不记录)

              ignoredups:忽略连续且相同的命令的历史缓存

              ignorespace:忽略以空白字符开头的命令(可用来无记录的删除历史记录)

              ignoreboth:以上两个功能都启用

显示出了历史命令之后就可以根据需要的历史命令的编号或者特征来调用:

       !number:重复执行第number条命令

       !string:从历史缓冲区中查找最近一次执行过的以“string”开头的命令

       !?string:从历史缓冲区中查找包含字符串“string”的命令

       !-n:执行缓冲区中倒数第n条命令(+为正数)

       ctrl+r:在历史缓冲区中搜索,搜索到了之后回车即可执行

与这个命令相类似的功能是使用之前使用过的命令中的参数:

       !$:最后一个命令中最后一个参数

       先按esc松手再按“.”也能补全

       alt+“.”:同上

       !^:上一个命令中的第一个位置的参数

       !:2:第二个参数

       !39:2:把history中第39个命令的第二个参数当作新参数

       !*:所有参数

       !STRING:^|$|*|NUMBER:

三、快捷键

在linux的帮助(man)中能够发现一些“C-1”类似的字符的介绍就是快捷键,在这些内容中C代表ctrl,M代表alt,E代表esc,DEL代表backspace。常见的组合快捷键有:

C-1(ctrl+l):清屏等同于clear

              如果当前没有输入,那么重启一行,其余上挪

              如果当前有输入,那么把当前行置顶

       C-a:将光标放到编辑行首

       C-e:将光标放到编辑行尾

       C-k:删除光标所在位置至行尾的命令行信息

       C-u:删除光标所在位置至行首的命令行信息

       C-c:结束前台进程,取消当前命令的执行

这些快捷键在我们使用bash的时候能够给我们带来极大的帮助比方说当你输入一长串命令之后却发现在这个命令的开头有个错误,那么一个一个的把光标移到开头就不如使用Ctrl+a键,然后再移回行尾就可以使用Ctrl+e键。

四、命令补全机制

命令补全既可以补全命令,也可以补全一个命令里的参数。使用的方法是当你输入一个命令的时候只需要输入前几个字符,然后摁一下Tab键,如果能够在众多命令中唯一的识别出你输入的命令,就会将其补全;如果给出的字符串不能作为唯一标识,则bash不予补全,再次敲击TAB键,bash会给出参考列表,如果参考列表中的内容过多,bash会询问是否显示该列表如果“空格”+TAB,那么bash会把当前工作目录中的文件打印出来。

五、命令行展开(可以使用echo查看)

       ~:bash会自动将其展开为当前登陆用户的家目录

       ~String:bash会将其自动展开为以String为用户名的家目录

       ~+:调用SHELL变量PWD的值

       ~-:调用SHELL变量OLDPWD的值

       {}:在花括号中可以填充一个以“,”分隔的路径列表,bash会将其展开为多个独立的路径

              {}中以“,”分隔的为命令的多个参数

                     {}可以嵌套

              举例:

1.创建a_a,a_b,b_a,b_b目录

                     mkdir{a,b}_{a,b}

2.使用touch命令基于花括号展开的方式创建如下文件:ace  acf  acg ade  adf  adg bce  bcf  bcg bde  bdf  bdg

                            touch{a,b}{c,d}{e,f,g}

六、命令的执行结果

       任何一个linux命令都有两种执行结果,第一种是命令的正常输出结果,跟用户需求相关的返回内容,比如当输入命令ls的时候会显示当前目录下的文件和目录,这些输出可以被别的命令引用,比如:echo`ls`,这条命令的含义是使用echo打印出ls命令要输出的内容(正常情况下只用ls命令输出的内容会有颜色,而使用这种方法输出的内容是没有颜色的,利用这一点可以进行区分)。与这种方法类似的还有echo $(ls),这是标准的命令引用格式。

第二种是命令的执行状态返回值,这是跟命令执行成功与否相关的返回内容,保存在bash的一个特殊变量中:$?。使用echo $?命令可以查看,如果输出的值是0则代表命令执行成功,其他的所有数字都代表执行失败。常见的失败数字有1,2,127,这些是bash内置状态返回值,1表示小问题,2表示严重问题, 127表示命令本身出问题。剩下的3-126,128-255表示用户自定义的状态信息(具体的命令的返回值代表的含义可以使用每个命令的–help选项查看)。

七、引用功能

        ‘**’:强引用(不进行变量替换),凡是被单引号引用的内容,bash一律将其视为普通字符,即便其本身有特殊功能和作用也是如此。但单引号本身是个例外例如: ‘’’,当输入这个命令后bash会根据就近匹配的原则认为当前的输入还没有完成。

        “**”:弱引用(如果名字里有空格最好加上引号),被双引号引用的内容中,有一些特殊字符仍然会保留其特殊含义,比如说:$,\

              例子:1. echo ‘$PATH‘

                            echo"$PATH"

                     2.备份/etc/整个目录的内容到/tmp,要求保存所有信息(链接等)

                            cp-a /etc/ /tmp/etc-$(date +"%F-%T")

八、转义功能,使用“\”号能够达到转义的功能,但是这个符号只能使其后紧跟的一个字符拥有或者失去特殊意义,比如:echo "$PATH"和echo"\$PATH"输出的信息是不同的,\将$符号的特殊意义去掉,使其变为了一个普通的字符。又比如:使用echo显示“The year is 2017. Today is March 5.”为两行——echo -e "The year is 2017. \nToday is March 21.",在这里\又使n拥有了换行的功能。当在末尾加上\的时候会使回车失效,在下一行需要继续输入,这个功能在调整输入输出格式的时候会很有用。

九、Globbing(文件名通配,简称为glob,简单的正则表达式匹配)

       通配语句基本由以下三种符号和一些判别内容组成。

       *:匹配任意长度的任意字符,某些特殊位置的“.”字符不能匹配

       ?:匹配任意单个字符,并且必须只有一个字符被匹配

       []:匹配指定范围内的任意单个字符,必须且只有一个字符被匹配

判别内容有:

              [a-z]代表a,A,b,B...Y,z(小写大写交替出现)

              [A-Z]代表A,b,B,c...z,Z

              [abcd...]代表小写字母

            因为以上的方法有一定的限制和不方便,所以有了字符集(使用的时候要嵌套[]使用),如下所示:

                     [:lower:]:所有的小写字母

                     [:upper:]:所有的大写字母

                     [:alpha:]:所有字母字符

                     [:digit:]:所有十进制数字

                     [:alnum:]:所有的大小写字母以及十进制数字

                     [:space:]:表示空白字符

                     [:punct:]:所有的标点符号

                     ^:取反(不包含)

举例:显示/etc/目录下,以非字母开头,且其后跟了一个字母以及其他任意字符的文件名

              ls-d /etc/[^[:alpha:]][[:alpha:]]*

十、输入输出(IO)重定向

在计算机中将显示器当作标准输出,将键盘当作标准输入,将输出到显示器的错误当作标准错误输出。使用文件描述符FD(File Descriptor(16位二进制))来描述信息是那种类型:

0代表标准输入stdin,1代表标准输出stdout,2代表标准错误stderr。而IO重定向就是指不是从标准输入、标准输出设备流动的数据。

       输出重定向有两种方法一种是使用一个“>”号的覆盖输出重定向,这个符号可以把原本输出到显示器的内容输出到一个文件,例如:echoabc > a这条命令的功能是将要通过echo输出的abc不显示到显示器上而是保存在当前目录下的a文件中。第二种是两个>号,也就是“>>”,这个符号的功能基本上和第一个是一样的,但是第一种在保存文件的时候会覆盖a文件里的内容,而这个不会,所以这个符号叫做追加输出定向符。

       错误重定向的方法和输出几乎一样,但是在>或>>之前要加一个数字2,代表输出错误。格式为2>:覆盖错误重定向,2>>:追加错误重定向。这两种方法能够合并输出重定向,有两种方法:第一种:&>,&>>(bash4.0之后才有),第二种:COMMAND >(或>>)/PATH/TO/SOMEFILE 2>&1(把错误和1放一块)

       针对linux的这种重定向的特性,于是就有了一个BitBucket(位桶),这个桶的功能就像一个垃圾桶,把不要的东西放进去,目录在/dev/null:BlackHole。衍生出来的功能有如果执行一个命令,只想知道其是否执行成功,而不想显示其输出的结果的作用,比如:

ls /tmp/a.txt &> /dev/null

ls /tmp/a.txt > /dev/null 2>&1(两者等价)

在执行以上两条命令中的任意一条之后,不会有输出结果,但是却可以通过echo $?显示命令执行是否成功。

       最后一种是输入重定向,它需要的符号是“<”,很多命令没有显示这个符号是因为对于大多数命令来说这个符号可以省略,比如:cat< /etc/a.txt 就等同于 cat /etc/a.txt。也有一部分命令因为其后没有给出对应输入参数的位置,比如:tr ‘a-z’ ‘A-Z’ < a.txt,这条命令的功能是将a.txt中的内容导入,并将其中的小写字母变成大写字母(tr还有很多其他的功能比如将第一个命令改为“-d”可以完成删除指定字符的功能),再比如:wc << a(输入字符,当遇到a的时候结束),cat > a.txt <<a (当遇到a的时候结束,把字符保存到a.txt),tr ‘a-z‘ ‘A-Z‘ << eof(输入字符串,当输入eof的时候结束,结束后将输入的字符串小写变为大写后输出)。

十一、管道

管道的功能是把一个命令的输出结果传递给下一个命令,比如:截取a.txt文件中的第九行

       head-n 9 a.txt | tail -n 1

管道的格式为:COMMAND1|COMMAND2|...

       值得注意的是所有的用于管道连接的命令,都应该是能够有标准输出数据流的命令

       在管道中如果既想将输出结果保存在文件中,又想显示在显示器上,那么就可以使用tee命令:标准输出、重定向输出同时输出,例如:echo aaa | tee a.txt(打印aaa到显示器上,同时保存到a.txt文件中)。可以使用管道来统计一个目录下有多少文件/目录:ls -d /etc/* | wc -l。

Bash