天天看点

Linux 上 Bash 的基础特性

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/gongxifacai_believe/article/details/83383829

1、命令历史

shell进程会在其会话中保存此前用户提交执行过的命令。

(1)

~]# history

定制history的功能,可通过环境变量实现:

1)HISTSIZE:shell进程可保留的命令历史的条数;

2)HISTFILE:持久保存命令历史的文件;

3).bash_history:用户登出时保存命令历史的文件(用户家目录下的隐藏文件)。每次用户登录,将.bash_history文件中的命令加载到内存中,之后在shell中执行history,显示的是内存中的命令,包括登录时加载的.bash_history命令和刚刚输入的命令。cat .bash_history 显示的是.bash_history中的命令,没有刚刚输入的命令,因为只有在用户登出时才将刚刚输入的命令保存到.bash_history文件中。

4)HISTFILESIZE:命令历史文件的大小。

命令用法:

(2)

history [-c] [-d 偏移量] [n] 操作文件

history -anrw [文件名]

history -ps 参数 [参数...]

-c: 清空命令历史;

-d offset:删除指定命令历史;

(3)

history -d offset n

:从命令编号为offset开始删除n条;

-r:从文件读取命令历史至历史列表中;

-w:把历史列表中的命令追加至历史文件中;

(4)

history #

:显示最近的#条命令;

(5)调用命令历史列表中的命令:

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

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

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

注意:命令的重复执行有时候需要依赖于幂等性;

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

快捷键:ESC, . (ESC松开后再按.)

快捷键:Alt+. (按住Alt再按.)

字符串:!$ (直接输入!$)

需要注意的是:连续执行相同的命令,在历史记录里面只记录一次。

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

环境变量:

HISTCONTROL

(在/etc/profile配置文件中控制)

ignoredups:忽略重复的命令,连续且相同方为“重复”;

ignorespace:忽略以空白字符开头的命令;

ignoreboth:以上两者同时生效;

修改变量的值:NAME=‘VALUE’

eg.

HISTCONTROL=ignorespace

,该修改仅对当前shell进程有效。

环境变量修改永久生效:export 变量名=“值”

2、命令操作

(1)命令补全

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

命令查找机制:

  1. 查找内部命令;
  2. 查找外部命令:根据PATH环境变量中设定的目录,自左而右逐个搜索目录下的文件名。

给定的打头字符串如果能惟一标识某命令程序文件,则直接补全;不能惟一标识某命令程序文件,再击tab键一次,会给出列表。

(2)路径补全

在给定的起始路径下,以对应路径下的打头字串来逐一匹配起始路径下的每个文件。

如果能惟一标识,则直接补全;否则,再一次tab,给出列表。

(3)命令行展开

~:自动展开为用户的家目录,或指定的用户的家目录;

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

例如:

/tmp/{a,b}

相当于

/tmp/a /tmp/b

(4)命令的执行状态结果

bash通过状态返回值来输出此结果:成功返回0,失败返回1-255之间的值。

命令执行完成之后,其状态返回值保存于bash的特殊变量

$?

中。

命令正常执行时,有的还会有命令返回值,根据命令及其功能不同,结果各不相同。

引用命令的执行结果:

$(COMMAND)

COMMAND

3、引用

强引用:’ ',其中任何内容直接显示,不做替换。

弱引用:" ",其中变量做变量替换,将出现变量的地方替换成变量的值。

命令引用:``

4、快捷键

Ctrl+a

:跳转至命令行行首;

Ctrl+e

:跳转至命令行行尾;

Ctrl+u

:删除行首至光标所在处之间的所有字符;

Ctrl+k

:删除光标所在处至行尾的所有字符;

Ctrl+l

:清屏,相当于clear;

Ctrl+c

:取消命令的执行;

5、globbing

globbing用于文件名通配,是整体文件名匹配,而非部分文件名匹配。

匹配模式

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

例:pa*, * pa *, * pa, *p * a *

(2)?:匹配任意单个字符;

例:pa?, ??pa, p?a, p?a?

(3)[]:匹配指定范围内的任意单个字符;

有几种特殊格式:

1)[a-z], [A-Z], [0-9], [a-z0-9];

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

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

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

5)[[:digit:]]:所有数字;

6)[[:alnum:]]:所有的字母和数字;

7)[[:space:]]:所有空白字符;

8)[[:punct:]]:所有标点符号;

(4)[^]:匹配指定范围外的任意单个字符;

例:[ ^ [:upper:]],[ ^ 0-9],[ ^ [:alnum:]];

例1:显示/var目录下所有以l开头,以一个小写字母结尾,且中间出现一位任意字符的文件或目录:

ls -d /var/l?[[:lower:]]

例2:显示/etc目录下,以任意一位数字开头,且以非数字结尾的文件或目录:

ls -d /etc/[0-9]*[^0-9]

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

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

例4:复制/etc目录下,所有以m开头,以非数字结尾的文件或目录至/tmp/magedu.com目录:

cp -r /etc/m*[^0-9] /tmp/magedu.com/

例5:复制/usr/share/man目录下,所有以man开头,后跟一个数字结尾的文件或目录至/tmp/man/目录下:

cp -r /usr/share/man/man[0-9] /tmp/man/

例6:复制/etc目录下,所有以.conf结尾,且以m,n,r,p开头的文件或目录至/tmp/conf.d/目录下:

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

6、IO重定向

(1)可用于输入的设备:键盘设备、文件系统上的常规文件、网卡等;

可用于输出的设备:显示器、文件系统上的常规文件、网卡等;

(2)程序的数据流有三种:

输入的数据流 <-- 标准输入(stdin)(键盘);

输出的数据流 --> 标准输出(stdout)(显示器);

错误输出流 --> 错误输出(stderr)(显示器);

标准输入用0表示,标准输出用1表示,错误输出用2表示。

(3)IO重定向

输出重定向:>

(特性:覆盖输出)

输出重定向:>>

(特性:追加输出)

输入重定向:<

Here Document:<< 此处创建文档,把所输入的内容创建为文档。

(4)输出重定向

set命令:

设置或撤销shell选项的值和位置参数

# set -C

禁止覆盖输出重定向至已存在的文件,该命令仅对当前shell进程有效,此时可使用强制覆盖输出:>|。

# set +C

关闭上述特性。

错误输出流重定向:2>, 2>>

例:

[root@localhost exercise]# cat /etc/issue1 2> issue1.err

合并正常输出流和错误输出流:

1)&>, &>>

例:

cat /etc/fstab3 &> fstab3.out

2)COMMAND > /path/to/somefile 2>&1 覆盖输出

COMMAND >> /path/to/somefile 2>>&1 追加输出

例:

cat /etc/rc.d/init.d/functions2 >> function.out 2>&1

特殊设备:/dev/null 数据黑洞

[root@localhost exercise]# ls /varr &> /dev/null
[root@localhost exercise]# echo $?
2
[root@localhost exercise]# ls /var &> /dev/null
[root@localhost exercise]# echo $?
0
对输出结果不关心,关心命令的状态结果           

复制

(5)输入重定向:<

tr命令:

tr [OPTION]... SET1 [SET2]

把输入的数据当中的字符,凡是在SET1定义范围内出现的,通通对位转换为SET2出现的字符。

1)用法1:

tr SET1 SET2 < /PATH/FROM/SOMEFILE

将SOMEFILE中SET1中出现的字符替换成SET2,并输出至屏幕(SOMEFILE原文件不改变)。

2)用法2:

tr -d SET1 < /PATH/FROM/SOMEFILE

从SOMEFILE中移除SET1中的字符,并输出至屏幕(SOMEFILE原文件不改变)。

注意:不修改原文件。

[root@localhost exercise]# tr [a-z] [A-Z]
how are you?
HOW ARE YOU?				
[root@localhost exercise]# tr [a-z] [A-Z] < /etc/issue
\S
KERNEL \R ON AN \M				
[root@localhost exercise]# tr -d 'abc' < /etc/issue
\S
Kernel \r on n \m				
[root@localhost exercise]# tr -d '[A-Z]' < /etc/issue
\S
ernel \r on n \m
[root@localhost exercise]# cat /etc/issue
\S
Kernel \r on an \m

把/etc/passwd文件的前6行的信息转换为大写字符后输出:
head -n 6 /etc/passwd | tr 'a-z' 'A-Z'
或者:[root@localhost exercise]# cat /etc/passwd | head -6 |tr 'a-z' 'A-Z'           

复制

(6)Here Document:<< 此处创建文档,把所输入的内容创建为文档

cat << EOF EOF为结束符

cat > /PATH/TO/SOMEFILE << EOF

[root@localhost exercise]# cat << EOF
> how are you?
> what are you doing?
> EOF
how are you?
what are you doing?
[root@localhost exercise]# cat > cat.out <<END
> how are you?
> what are you doing?
> END
[root@localhost exercise]# cat cat.out
how are you?
what are you doing?           

复制

7、管道

管道:连接程序,实现将前一个命令的输出直接定向后一个程序当作输入数据流,前一个命令的输出作为后一个命令的输入。

COMMAND1 | COMMAND2 | COMMAND3 | ...

[root@localhost exercise]# cat /etc/issue | tr 'a-z' 'A-Z'
\S
KERNEL \R ON AN \M						 
[root@localhost exercise]# who
root     :0           2016-11-16 07:21 (:0)
root     pts/0        2016-11-16 07:21 (:0)
root     tty2         2016-11-16 07:25
[root@localhost exercise]# who | head -2
root     :0           2016-11-16 07:21 (:0)
root     pts/0        2016-11-16 07:21 (:0)
[root@localhost exercise]# who | head -2 | tr 'a-z' 'A-Z'
ROOT     :0           2016-11-16 07:21 (:0)
ROOT     PTS/0        2016-11-16 07:21 (:0)
[root@localhost exercise]# who | head -2 | tr 'a-z' 'A-Z' | tr -d '0-9'
ROOT     :           -- : (:)
ROOT     PTS/        -- : (:)           

复制

(1)tee命令

从标准输入读入,并写往标准输出和文件。

COMMAND | tee /PATH/TO/SOMEFILE

[root@localhost exercise]# cat /etc/issue | tee issue.tee | tr 'a-z' 'A-Z'
\S
KERNEL \R ON AN \M
[root@localhost exercise]# cat issue.tee
\S
Kernel \r on an \m           

复制

8、命令hash

(1)hash的作用

hash就是记录或显示程序的位置(可执行程序的位置)。如果我们执行程序,系统每次都要从目录里面查找可执行文件,如果目录里面有很多可执行程序,那每次都需要花费很多时间去找文件,这就势必导致系统响应很慢,当然这也很不现实。实际中是只有第一次才去完整查找命令执行文件的,然后将其查询的结果记录下来放置到缓存中,如果下次还需要执行同样的命令,那么就直接从缓存中找命令的执行文件,然后直接执行。

这个缓存就是一个key/value的存储,可以通过hash命令来查看这个命令的缓存结果,这里的value就是命令的可执行文件的路径,key是一段hash码。

将一个命令移入到另一个目录里面来执行该命令,如:mv /bin/ls /usr/bin/ls,再执行ls命令,会发现系统找不到ls命令了。

(2)hash的使用

hash:列出hash缓存,缓存此前命令的查找结果:key-value,key为搜索键,value为值;

通过内部命令获取帮助信息的方式来获取hash命令的使用方法:

help hash

hash -d COMMAND:删除hash中的某一条命令,COMMAND不需要给完整路径,只需要给命令名称即可;

hash -r:清空hash缓存。

[root@localhost ~]# hash
hits	command
1	/usr/bin/grep
1	/usr/bin/ls
[root@localhost ~]# hash -d ls
[root@localhost ~]# hash
hits	command
 1	/usr/bin/grep
[root@localhost ~]# hash -r
[root@localhost ~]# hash
hash: hash table empty           

复制

9、变量

(1)变量类型定义了数据存储格式、存储空间大小、参与的运算种类、表示的数据范围等。变量有强类型和弱类型。强类型是指定义变量时必须指定类型、参与运算必须符合类型要求,如果调用未声明变量的,则会产生错误。弱类型是指无需指定类型,默认均为字符型,参与运算会自动进行隐式类型转换,变量无需事先定义可以直接调用。bash就属于弱类型的编程语言。

变量的类型有:字符型、数值型。数值型又分为整型和浮点型。

bash是弱类型语言,把所有变量统统视作字符型,当我们强行指明做数值加减运算时,可以转换为数值型。bash不支持浮点数据,除非我们借助外在工具。

变量声明:bash中的变量无需事先声明,相当于把声明和赋值过程同时实现。

变量替换:把变量名出现的位置替换为其所指向的内存空间中数据。

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

变量名:变量名只能包含数字、字母和下划线,而且不能以数字开头。

变量名:见名知义,命名机制遵循某种法则,不能够使用程序的保留字,例如if, else, then, while等等。

shell可以有子shell,子shell又可以有子shell,并且父shell和子shell的shell类型可以不同(如,父shell为bash,子shell为csh),使用exit退出当前shell,回到父shell。

(2)bash变量类型

本地变量:作用域仅为当前shell进程;

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

局部变量:作用域仅为某代码片断(函数上下文);

位置参数变量:向执行脚本的shell进程传递的参数;

特殊变量:shell内置的有特殊功用的变量;如 $ ?,用于表示命令执行的状态结果,0表示成功,1-255表示失败。

(3)本地变量

生效范围为当前shell进程,对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效。

变量赋值:name=‘value’,其中value可以是直接字符串:name=“username”,变量引用:name="$username",也可以是命令引用:name=COMMAND(反引号),name= $(COMMAND)。

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

“ ”:弱引用,其中的变量引用会被替换为变量值;

’ ':强引用,其中的变量引用不会被替换为变量值,而保持原字符串。

显示已定义的所有变量:set,CentOS6和CentOS7执行set不同,CentOS7会显示shell内置的函数;

撤销变量:unset name;注意:此处非变量引用;不加 $。

[root@localhost ~]# first_name=jerry
[root@localhost ~]# echo $first_name
jerry
[root@localhost ~]# unset first_name
[root@localhost ~]# echo $first_name

[root@localhost ~]#            

复制

(4)环境变量:变量作用域可以用于子shell,可以多级继承

变量赋值:

1)export name=value
2)name=value
export name
3)declare -x name=value     declare是bash内嵌命令,可以导出变量;
4)name=value
declare -x name
declare -i name              声明整型变量(bash数值型变量只支持整型,不支持浮点型)           

复制

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

bash内嵌了许多环境变量(通常为全大写字符),用于定义bash的工作环境:

PATH, HISTFILE, HISTSIZE, HISTFILESIZE, HISTCONTROL, SHELL, HOME, UID, PWD, OLD, OLDPWD, PS1等。

查看环境变量:

export, declare -x, printenv, env

撤销环境变量:

unset name

只读变量:

1)declare -r name
2)readonly name           

复制

只读变量无法重新赋值,并且不支持撤销,存活时间为当前shell进程的生命周期,随shell进程终止而终止。

(5)局部变量:生效范围为当前shell进程中的某代码片段(通常指函数)。

(6)位置变量:$ 1,…,$ n,$ {10}来表示,用于在脚本代码中调用通过命令行传递给它的参数。

(7)特殊变量

$?:上个命令执行成功与否的结果;

$0:表示命令本身;

$#:传递给脚本参数的个数;

$*:传递给脚本的所有参数;

$@:引用传递给脚本的所有参数。

10、多命令执行

~]# COMMAND1; COMMAND2; COMMAND3; ...

11、逻辑运算

短路法则:

~]# COMMAND1 && COMMAND2

COMMAND1为“假”,则COMMAND2不会再执行,否则,COMMAND1为“真”,则COMMAND2必须执行。

~]# COMMAND1 || COMMAND2

COMMAND1为“真”,则COMMAND2不会再执行,否则,COMMAND1为“假”,则COMMAND2必须执行。

[root@localhost ~]# touch /tmp/test.etc && ls /etc > /tmp/test.etc
[root@localhost ~]# touchabc /tmp/test.etc2 && ls /etc > /tmp/test.etc2
bash: touchabc: command not found...
[root@localhost ~]# cat /tmp/test.etc2
cat: /tmp/test.etc2: No such file or directory

~]# id $username || useradd $username       如果username不存在,则创建他
[root@localhost ~]# id user1
id: user1: no such user
[root@localhost ~]# id user1 || useradd user1
id: user1: no such user
[root@localhost ~]# id user1
uid=1003(user1) gid=1003(user1) groups=1003(user1)
[root@localhost ~]# id user1 || useradd user1
uid=1003(user1) gid=1003(user1) groups=1003(user1)           

复制

12、bash的配置文件

(1)bash配置文件的分类

bash的配置文件分为两类:

profile类:为交互式登录的shell进程提供配置;

bashrc类:为非交互式登录的shell进程提供配置。

(2) shell进程的分类

按照登录类型将shell进程分为两类:交互式登录shell进程和非交互式登录shell进程。

交互式登录shell进程:

1)直接通过某终端输入账号和密码后登录打开的shell进程;

2)使用su命令:su - USERNAME, 或者使用 su -l USERNAME执行的登录切换。

非交互式登录shell进程:

1)su USERNAME执行的登录切换;

2)图形界面下打开的终端;

3)通过运行脚本,shell脚本的运行是通过运行一个子shell进程实现的。

(3)profile类配置文件

全局配置文件(对所有用户都生效):

/etc/profile 主配置文件

/etc/profile.d/* .sh 配置文件片段

用户个人配置文件(仅对当前用户有效):

~/.bash_profile

profile类配置文件功用:

1)用于定义环境变量;

2)运行命令或脚本。

(4)bashrc类配置文件

全局配置文件(对所有用户都生效):

/etc/bashrc

用户个人配置文件(对某一用户生效):

~/.bashrc

bashrc配置文件功用:

1)定义本地变量;

2)定义命令别名。

仅管理员可修改全局配置文件,普通用户没有权限编辑。

(5) 配置文件的读取顺序

交互式登录shell进程:

直接通过终端输入账号和密码登录,或者使用su -l USERNAME或su - USERNAME切换登录用户:

/etc/profile --> /etc/profile.d/* .sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc

非交互式登录shell进程:

使用su USERNAME或者图形界面下打开的终端,执行脚本

~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

(6)配置文件的生效

命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期。

配置文件定义的特性,只对随后新启动的shell进程有效。

让通过配置文件定义的特性立即生效:

1)退出并重新登录;

2)让shell进程重读配置文件;

~]# source /PATH/FROM/CONF_FILE
~]# .  /PATH/FROM/CONF_FILE         .的意思就是source命令           

复制

(7)设置用户登录欢迎语句

[root@localhost exercise]# nano /etc/profile.d/welcome.sh
welcome.sh文件内容:
echo "Welcome aboard..."           

复制

不需要赋予权限,下次登录时即可加载该配置文件,全部用户登录时都可看到欢迎语句。