Linux shell之bash特性大全详解(持续更新ing)

一、shell是什么?

    Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁,用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

    如图shell是一个应用程序,是用户管理应用程序的一个接口。

wKioL1ba5wXDNSCsAABtio430hE601.png

二、广义上shell的分类

    GUI:图形用户界面

        KDE,GNOME,XFCE

    CLI:命令行接口

        bash, zsh, fishsh, csh, tcsh, ksh

在大多发行版中常用的为bash

三、bash的特性

bash是弱类型的编程语言,不严格区分数据类型,意味把所有数据统统当作字符串处理;

字符串类型的数据可不加引号; 

引号有三种类型:', ", `

', ":字符引用

': 强引用,其内部的变量不会被替换; 

":弱引用,其内部的变量会被替换;

`:命令引用

变量引用:${NAME}

a、bash特性之一:命令别名

    获取当前用户可用的别名的定义:

# alias

    定义别名:

# alias  NAME='COMMAND'

    生命周期:当前shell进程;

    撤消别名:

# unalias NAME

b、bash的特性之二:命令历史

    shell进程会保存其会话中用户曾经执行过的命令;命令通过其“历史文件”来持久保存此前执行过的命令;每个用户都有其自己专用的历史文件;

HISTSIZE:shell进程的缓冲区保留的历史命令的条数;

HISTFILESIZE:命令历史文件可保存的历史命令的条数;

    默认均为1000;       

# echo $HISTSIZE
1000
# echo $HISTFILESIZE
1000

        HISTFILE:当前用户的命令历史文件;

    ~/.bash_history

查看命令历史列表:

# history

    命令用法:

history -c:清空命令历史;

history  -d  OFFSET:删除指定的条目;

# history -d 156

    -a        将当前缓冲的历史行追加到历史文件中

    -n        从历史文件中读取所有未被读取的行

    -r        读取历史文件并将内容追加到历史列表中

调用命令历史列表中的命令以重执行之目的:

    !#:再一次执行历史列表中的第#条命令;

# history
   ....
   72  cat test 
   73  history 
# !72
cat test 
Hello World

            !!:再一次执行上一条命令;

# cat test 
Hello World
# !!
cat test 
Hello World

            !STRING:再一次执行命令历史列表中最近一个以指定的STRING开头的命令;

# !cat
cat test 
Hello World

            调用上一条命令的最后一个参数:

快捷键:ESC, .

                     Alt+.

!$:给出的字符组合

    显示最近的n条件命令历史:

    history  #

    控制命令历史的记录方式:

通过HISTCONTROL环境变量进行,其取值:

    ignoredups:忽略重复的命令;重复是指连续且相同的令;

    ignorespace:以空白字符开头的命令不记入历史;

    ignoreboth:上述两者同时生效;

        修改变量值的方式:

    NAME='VALUE'

# echo $HISTCONTROL
ignoredups
# HISTCONTROL="ignoreboth"
# echo $HISTCONTROL
ignoreboth

c、bash特性之三:快捷键 

Ctrl+a:跳至命令行首;

Ctrl+e:跳至命令行尾;

Ctrl+k:删除光标所在处至尾部的内容;

Ctrl+u:删除行首至光标所在处的内容;

d、bash的特性之四:命令补全和路径补全

    命令补全:

shell程序在接收到用户执行命令的请求且分析完成之后,最左侧字符串将被当作命令去查找;

      查找机制:

(1) 查找内部命令;

(2) 查找外部命令:

    1、去$PATH变量所指定的各路径下,自左而右逐个搜索各目录下的文件名;

    2、给定的打头的字符串如果能惟一标识某命令程序文件的文件名,则直接补全;

    3、不能惟一标识,再击tab可给列表;

    4、错误:没有任何命令可被此打头字符串标识;

       路径补全:

在给定的起始路径的上级目录下,以对应路径下的打头字符串来逐一匹配上级目标下的每个文件:

惟一标识:tab补全;

不能惟一标识:tab, tab给出列表;

错误路径:没有响应;

e、bash的特性之五:命令行展开:

    把命令行的给定的特殊符号自动替换为相应字符串的机制;

~: 自动替换为用户家目录;

~USERNAME:自动替换为指定用户的家目录;

{}:可承载一个以逗号分隔的路径列表,能够将其展开为多个独立路径;

            例如:

                /tmp/{a,b,c} /tmp/a /tmp/b /tmp/c

                /tmp/{a,b}/z /tmp/a/z /tmp/b/z

# cd ~
# pwd
/root
# cd ~testuser
testuser]# pwd
/home/testuser

f、bash特性之六:命令的执行状态结果:

命令的正常输出结果:命令的返回值;

    通过引用来保存下来或直接调用——”命令引用“

`COMMAND`

$(COMMAND)

# ls -ld `pwd`

命令的执行状态结果:

成功:0

失败:1-255

# echo "Helllo World"
Helllo World
# echo $?
0
# echoa "Hello World"
-bash: echoa: command not found
# echo $?
127

        bash用一个特殊变量来保存最一次执行的命令的状态结果:

$?

bash中的引用:

'':强引用

"":弱引用

“:命令引用

# echo '$PATH'
$PATH
# echo "$PATH"
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
# echo `pwd`
/home/testuser

g、bash的特性之七:glob

    glob:文件名通配;快速引用多个文件;文件名整体匹配度检测;    

    元字符:基于元字符可编写匹配模式(pattern);

        *:匹配任意长度的任意字符;

p*,  pa*, *p, *p*a

p*:pa, p

?:匹配任意单个字符;

            p?, p?a, p??

    p??: pa, pad, 

[ ]:匹配指定集合内的任意单个字符;

         [a-z], [A-Z]:不区分字符大小写;

[0-9]

        [a-z0-9]

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

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

            [[:digit:]]:所有的数字;

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

    [[:alnum:]]:所有字母和数字;

    [[:space:]]:空白字符;

    [[:punct:]]:标点符号;

    [^ ]:匹配指定集合外的任意单个字符;

[^[:alpha:]]

    测试:

     1、显示/etc目录下,以非字母开头,后面跟了一个字母及其它任意长度任意字符的文件或目录; 

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

     2、复制/etc目录下,所以n开头,以非数字结尾的文件或目录至/tmp/etc目录下;

    mkdir /tmp/etc 
    cp  -r  /etc/n*[^0-9]  /tmp/etc/

     3、显示/usr/share/man目录下,所有以man开头,后跟一个数字结尾的文件或目录;

    ls  -d  /ur/share/man/man[0-9]

     4、复制/etc目录下,所以p,m,r开头的,且以.conf结尾的文件或目录至/tmp/conf.d目录下;

    mkdir  /tmp/conf.d/
    cp  -r  /etc/[pmr]*.conf   /tmp/conf.d/

h、bash特性之八:变量

程序:指令+数据

数据:文件、变量;

    变量:内存空间,有名称,名称即为变量名,对应的内存空间中的数据即为变量的值;

    变量赋值:NAME=VALUE

=:赋值符号;

把VALUE存储到NAME指向的内存空间中;

编程语言:

强类型:严格区分变量中的数据类型;

弱类型:不区分变量中存储的数据类型,统一为字符型;

bash:统统默认为字符型数据;变量无需事先声明;

变量为什么有类型?

存储空间、存储格式、参与的运算、……

        类型不同决定对数据的处理方式不同

变量命名:只能使用字母、数字和下划线;而且不能以数字开头;


变量名:见名知义;不能使用程序保留字,例如if、case、then、fi、esac、for、while、until、break、continue等等;

变量引用:${NAME}, $NAME

         变量替换:把变量引用符号出现的位置替换为其指向的内存空间中的数据;

bash变量种类:

本地变量:作用域为当前shell进程;不包括其子进程;

环境变量:使用域为当前shell进程及其子进程;

局部变量

    作用域:生效范围,也即可引用到的范围;

位置参数变量:

特殊变量

本地变量:

变量赋值:NAME=VALUE

变量引用:$NAME, ${NAME}

""

查看变量:set

撤销变量:unset NAME

注意:此处非为变量引用,因此不能使用$;

所有的本地变量在shell进程终止时,会被自动撤销;

   

环境变量:

变量声明和赋值:

declare -x  NAME[=VALUE]

export  NAME[=VALUE]

引用方式:

${NAME}, $NAME

注意:bash内嵌了许多环境变量,名称为全大写字母,例如UID、HOME、PWD、SHELL, PATH, HISTSIZE等等;

环境变量查看:

export, declare  -x

env,  printenv

撤销环境变量:

unset  NAME

只读变量:常量

(1) declare  -r  NAME

(2) readonly  NAME

不支持重新赋值,也不支持撤销操作;

# declare -r username=`whoami`
# echo $username
root
# unset username
-bash: unset: username: cannot unset: readonly variable

i、bash基于特性之九:I/O重定向和管道

程序的数据流有三个:

    输入数据流: <–,标准输入(stdin),键盘;

    输出数据流:–>,标准输出(stdout), 显示器;

    错误数据流:–>,错误输出(stderr),显示器;

fd:file descriptor,文件描述符;

stdin: 0

stdout: 1

stderr: 2

IO重定向:

输出重定向:

重定向程序正常执行的结果

COMMAND >  /PATH/TO/SOMEFILE

覆盖重定向:覆盖目标文件中的原有内容;

COMMAND >> /PATH/TO/SOMEFILE

         追加重定向:追加新产生的内容至目标文件尾部;

shell的一个功能开关:

# set -C

禁止覆盖输出重定向至已存在的文件;

注意:此时仍然可以使用“>|”至目标文件; 

# set +C

关闭上述特性;

错误重定向:

重定向错误的执行结果;

COMMAND 2>  /PATH/TO/SOMEFILE

错误输出覆盖重定向;

COMMAND 2>> /PATH/TO/SOMEFILE

错误输出追加重定向;

合并标准输出与错误输出流:

(1) &>, &>>

(2) COMMAND > /PATH/TO/SOMEFILE 2>&1

     COMMAND >> /PATH/TO/SOMEFILE 2>&1

特殊输出目标:/dev/null

位桶:bit bucket

特殊的输入文件:/dev/zero

输入重定向:

COMMAND < /PATH/FROM/SOMEFILE

tr命令:把输出的数据当中的字符,实现对位转换,即把数据中的存在于字符集中的字符,统统转换为字符集2中对应的字符;

tr – translate or delete characters

tr [OPTION]… SET1 [SET2]

(1) tr  SET1  SET2 < /PATH/FROM/SOMEFILE

字符转换

    # cat test 
    Hello World
    # cat test |tr 'a-z' 'A-Z'
    HELLO WORLD

(2) tr  -d  SET1  < /PATH/FROM/SOMEFILE

删除

# cat test 
    Hello World
    # cat test |tr -d 'ldH'
    eo Wor

COMMAND << :

Here Document

用法:

COMMAND << EOF

COMMAND > /PATH/TO/SOMEFILE << EOF

管道:

COMMAND1 | COMMAND2 | COMMAND3 | …

练习1:把/etc/passwd文件最后三行信息中所有小写字符改为大写后输出;

# tail -3 /etc/passwd|tr 'a-z' 'A-Z'
TEST1:X:5002:5002::/HOME/TEST1:/BIN/BASH
TEST2:X:5003:5003::/HOME/TEST2:/BIN/BASH
TEST3:X:5004:5004::/HOME/TEST3:/BIN/BASH

练习2:取出/etc/fstab的第6行;

# head -6 /etc/fstab |tail -1
# Accessible filesystems, by reference, are maintained under '/dev/disk'

练习3:取出/etc目录下所有以p开头的文件或目录,只显示前5个;

# ls -d /etc/p*|head -5
/etc/pam.d
/etc/passwd
/etc/passwd-
/etc/pinforc
/etc/pkcs11

tee命令:

tee – read from standard input and write to standard output and files

tee [OPTION]… [FILE]…

    -a:使用追加输出,而非覆盖;

        COMMAND | tee /PATH/TO/SOMEFILE

    # cat test|tee /tmp/test.cat
    Hello World
    # cat /tmp/test.cat 
    Hello World

原创文章,作者:Ace,如若转载,请注明出处:http://www.178linux.com/12259

评论列表(1条)

  • stanley
    stanley 2016-03-09 09:55

    赞,专业