bash特性
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bash特性相关的知识,希望对你有一定的参考价值。
bash的基础特性(1):
(1) 命令历史
history
系统中history环境变量:
HISTSIZE:命令历史记录的条数;
HISTFILE:~/.bash_history;
HISTFILESIZE:命令历史文件记录历史的条数;
history -d OFFSET(具体删除第几条历史记录)
history -c 清空所有历史记录
history #: 显示历史中最近的#条命令;
history -a: 手动追加当前会话缓冲区的命令历史至历史文件中;
调用历史中的命令:
!#: 重复执行第#条指令;
!!: 执行上一条指令
!string:最近一条以指定字符串开头的命令
调用上一条命令的最后一个参数:!$
cat /etc/fstab
ls -l !$
控制命令历史的记录方式:由环境变量HISTCONTROL来控制
环境变量:HISTCONTROL,有以下的值
ignoredups:忽略重复的命令;注意:连续且相同方为“重复”
ignorespace:忽略所有以空白开头的命令;
ignoreboth:ignoredups, ignorespace(即以上两个都生效);
修改环境变量值的方式:export 变量名="值",只对当前的shell有效。
export HISTCONTROL=“ignorespace”
(2) 命令补全
bash执行命令:
内部命令:
外部命令:bash根据PATH环境变量定义的路径,自左而右在每个路径搜寻以给定命令名命名的文件,第一次找到即为要执行的命令;
直接补全:Tab,用户给定的字符串只有一条惟一对应的命令;
以用户给定的字符串为开头对应的命令不惟一,则再次Tab会给出列表;
(3) 路径补全
把用户给出的字符串当做路径开头,并在其指定上级目录下搜索以指定的字符串开头的文件名;
如果惟一:则直接补全;
否则:再次Tab,给出列表;
(4) 命令行展开
~: 展开为用户的主目录
~USERNAME:展开为指定用户的主目录
{}:可承载一个以逗号分隔的列表,并将其展开为多个路径
/tmp/{a,b} = /tmp/a, /tmp/b
/tmp/{tom,jerry}/hi = /tmp/tom/hi, /tmp/jerry/hi
(5) 命令的执行结果状态
成功
失败
bash使用特殊变量$?保存最近一条命令的执行状态结果:
0:成功
1-255:失败
程序执行有两类结果:
程序的返回值;
程序的执行状态结果;
bash的基础特性(2):
1、命令别名(alias)
通过alias命令实现:
(1) alias
显示当前shell进程中所有可用的命令别名;
(2) alias NAME=‘VALUE‘:alias cdnet=‘cd /etc/sysconfig/network-script‘
定义别名NAME,执行NAME就相当于执行命令VALUE;
注意:在命令行中定义的别名,仅对当前shell进程有效;如果想永久有效,要定义在配置文件中;
仅对当前用户:~/.bashrc
对所有用户有效:/etc/bashrc
Note: 编辑配置给出的新配置不会立即生效,需要使进程重新读取配置文件(命令行会立即生效,但不会永久有效):
source /path/to/config_file
或者:. /path/to/config_file
撤消别名:unalias
unalias -a 撤销所有别名信息
unalias name 撤销具体某个别名
Note: 如果别名同原命令的名称,则如果要执行原命令,可使用"\COMMAND";
whatis COMMAND 查看命令有哪些章节
2、glob (globbing):实现文件名“通配”
通配符:*, ?, []
(1) *
任意长度的任意字符
a*b:
aab, ab, a123b,
abc
(2) ?
任意单个字符
a?b:
aab
ab, a12b, abc
(3) []
匹配指定范围内的任意单个字符
[0-9]:
[a-z]:不区分字符大小写
[A-Z]:仅匹配A-Z中的一个字符
(4) [^]
匹配指定范围外的任意单个字符
[^0-9]:不包含数字
专用字符集合:
[:digit:]:任意数字,相当于0-9
[[:digit:]]:相当于[0-9]
[:lower:]:任意小写字母
[:upper:]: 任意大写字母
[:alpha:]: 任意大小写字母
[:alnum:]:任意数字或字母
[:space:]:
[:punct:]:标点符号
练习:
1、显示/var目录下所有以l开头,以一个小写字母结尾,且中间出现至少一位数字的文件或目录;
# ls -d /var/l*[0-9]*[[:lower:]]
2、显示/etc目录下,以任意一位数字开头,且以非数字结尾的文件或目录;
# ls -d /etc/[0-9]*[^0-9]
3、显示/etc/目录下,以非字母开头,后面跟了一个字母及其它任意长度任意字符的文件或目录;
# ls /etc/[^[:alpha:]][[:alpha:]]*
4、复制/etc目录下,所有以m开头,以非数字结尾的文件或目录至/tmp/mageedu目录中;
# cp -a /etc/m*[^0-9] /tmp/mageedu
5、复制/etc目录下,所有以.d结尾的文件或目录至/tmp/magedu.com目录中;
# cp -a /etc/*.d /tmp/magedu.com
6、复制/etc目录下,所以有.conf结尾,且以m,n,r,p开头的文件或目录至/tmp/mageedu.com目录中;
# cp -a /etc/[mnrp]*.conf /tmp/mageedu.com
cp -a /etc/{m,n,r,p}*.conf /tmp/mageedu.com
3、bash的快捷键
Ctrl+l: 清屏,相当于clear命令;
Ctrl+a:跳转至命令开始处;
Ctrl+e:跳转至命令结尾处;
Ctrl+c:取消命令的执行;
Ctrl+u: 删除命令行首至光标所在处的所有内容;
Ctrl+k: 删除光标所在处至命令行尾部的所有内容;
4、bash的的I/O重定向及管道
打开的文件都有一个fd: file descriptor (文件描述符)
标准输入(默认从键盘输入):键盘的文件描述符用“0”表示
比如:cat命令,如果不给定参数,会等待键盘输入
标准输出(默认从显示器输出):显示器的文件描述符用“1”表示
标准错误输出(默认从显示器输出):显示器的文件描述符用“2”表示
I/O重定向:改变默认位置
>:覆盖重定向,目标文件中的原有内容会被清除;
>>: 追加重定向,新内容会追加至目标文件尾部;
# set -C: 禁止将内容覆盖输出至已有文件中(即禁止使用覆盖重定向已有的文件,只对当前shell生效);
强制覆盖:>|:cat /etc/fstab >| /etc/a
# set +C: 允许将内容覆盖输出至已有文件中
2>: 覆盖重定向错误输出数据流;
2>>: 追加重定向错误输出数据流;
标准输出和错误输出各自定向至不同位置:
COMMAND > /path/to/file.out 2> /path/to/error.out:COMMAND执行成功保存在/path/to/file.out文件中;COMMAND执行失败,保存在/path/to/error.out文件中
标准输出和错误输出重定向至同一个文件中:
&>:覆盖重定向
&>>:追加重定向
echo "PATH" &> /tmp/path.out 命令无论执行成功或错误,都重定向至/tmp/path.out文件中。
COMMAND > /path/to/file.out 2> &1
COMMAND >> /path/to/file.out 2>> &1
输入重定向:<
tr命令:转换或删除字符
tr [OPTION]... SET1(字符集1) [SET2](或字符集2)
-d :tr -d ‘U‘ 出现U的都删除
如果只给定一个字符集,就表示在给定的字符里,凡是在字符集1中出现的字符都移除
如果同时给定字符集1和字符集2,表示给定的字符将第一个字符集中出现字符替换成第二个字符集中的字符(按位替换)
tr abc ABC
输入:alpa 回车
输出:AlpA
tr abc ABC < /etc/fstab 在/etc/fstab文件中,所有出现a (b)( c)的字符替换为对应的A (B)( C)
HERE Documentation:<<
# cat << EOF
# cat > /path/to/somefile << EOF
例如:cat << EOF
> how are you 回车
>how old are you 回车
>EOF 回车
输出:how are you
how old are you 将以上输入合成一次输出
管道:第一个命令的输出作为第二个命令的输入
COMMAND1 | COMMAND2 | COMMAND3 |...
注意:最后一个命令会在当前shell进程的子shell进程中执行;
tee命令:
tee [OPTION]... [FILE]...
练习:
1、将/etc/passwd文件中的前5行内容转换为大写后保存至/tmp/passwd.out文件中;
2、将登录至将前系统上用户信息中的后3行的信息转换为大写后保存至/tmp/who.out文件中;
# who | tail -n 3 | tr ‘a-z‘ ‘A-Z‘ > /tmp/who.out
bash的基础特性(4)
变量类型:
数据存储格式、存储空间大小、参与运算种类;
字符型
数值型:
整型
浮点型
强类型:定义变量时必须指定类型、参与运算必须符合类型要求;调用未声明变量会产生错误;
弱类型:无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用;如bash
变量赋值:set VAR_NAME=VALUE set可省略(重启后该变量值会消失)
例NAME=Jerry 声明变量NAME,并附值为Jerry。声明的变量类型默认都为字符串类型,可用let sum=0直接声明sum为整数
引用变量的值:${VARNAME} 。{}有时可以省略。
declare 变量声明
declare -i SUM=0 声明sum这个变量为整数
-x 将变量声明为环境变量
bash支持的引号
`` :引用命令执行结果,而不是引用命令执行状态结果。 例如:userid=`id -u user1` 将id -u user1的执行结果付值变量userid;
"" :弱引用,可以实现内部变量替换。
‘‘:强引用,不完成变量替换。
变量名称:
1、只能包含字母、数字和下划线,并且不能数字开头;
2、不应该跟系统中已有的环境变量重名;
3、最好做到见名知义;
bash变量类型:
环境变量
本地变量(局部变量)
位置变量
特殊变量
1.本地变量:
(set)VARNAME=VALUE: 作用域为整个bash进程,bash进程结束变量也消失;
2.局部变量:
local VARNAME=VALUE:作用域为当前代码段;
3.环境变量:作用域为当前shell进程及其子进程;
export VARNAME=VALUE
或VARNAME=VALUE
export VARNAME (先设为本地变量然后再导出)
查看当前shell中的环境变量:printenv或env或export。
脚本在执行时会启动一个子shell进程;
命令行中启动的脚本会继承当前shell环境变量;
系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量;
4.位置变量:引用给定脚本的参数。 例 ./test.sh /etc/passwd /etc/rc.d/rc.sysinit
$1(第一个位置的参数 /etc/passwd), $2(第二个位置的参数 /etc/rc.d/rc.sysinit), …
支持shift 换岗操作:
Shift [n] 剔除几个位置变量,默认为1
例:shift
echo $1 (这时输出的是第二个参数值)
5.特殊变量:bash内置的用来保存某些特殊的变量
$?: 保存上一个命令的执行状态返回值;
$#:统计脚本参数的个数
$*:参数列表(把所有的参数看成一个字符串)
[email protected]:参数列表(把所有参数的每一个参数当成一个字符串)
$0: 执行脚本时,对指定的路径取基名即脚本名称
程序执行后,可能有两类返回值:
>程序执行结果
>程序状态返回代码(0-255)
0: 正确执行
1-255:错误执行,1,2,127系统预留;
撤消变量:unset VARNAME
查看当shell中变量:set
在变量中添加多个字符串:ANIMALS=pig:wolf:goat或ANMALS=$ANIMALS:wolf
在shell变量默认都是字符串,所以不能做算术运算。
数组赋值:
Array_Name=("element1" "element2")
也可以对元素进行一个个的赋值。
数组引用:
Array_Name[Index]
示例:判断给出的文件的行数
#!/bin/bash
linecount="$(wc -l $1| cut -d‘ ‘ -f1)" 命令结果有空格的话需要加""。
echo "$1 has $linecount lines."
bash的配置文件:
按生效范围划分,存在两类:
全局配置:
/etc/profile (对所有用户生效)
/etc/profile.d/*.sh(配置文件过大,会分割成多个片段)
/etc/bashrc
个人配置:(只对某一用户生效)
~/.bash_profile
~/.bashrc
按功能划分,存在两类:
profile类:为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功用:
(1) 用于定义环境变量;
(2) 运行命令或脚本;
bashrc类:为非交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用:
(1) 定义命令别名;
(2) 定义本地变量;
shell登录:
交互式登录:读取配置文件的顺序
直接通过终端输入账号密码登录;
使用“su - UserName”或“su -l UserName”切换的用户
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc(相同的变量,后面的会覆盖前面的值)
非交互式登录:读取配置文件的顺序
su UserName
图形界面下打开的终端
执行脚本
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
编辑配置文件定义的新配置的生效方式:
(1) 重新启动shell进程;
(2) 使用source或.命令进程;
问题:
1、定义对所有用户都生效的别名? /etc/bashrc
2、设置所有用户登录系统时输出提示信息? /etc/profile.d/*.sh
2、让用户的PATH环境变量的值多出一个路径,例如多如/usr/local/apache2/bin
export PATH=$PATH:/usr/local/apache2/bin (不能永久有限)
bash中的算术运算
help let 查看shell支持的算术运算有哪些
+, -, *, /, %, **
实现算术运算:
(1) let var=算术表达式
num1=1 num=3
let sum=$num1+$num2
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 ...)
乘法符号有些场景中需要转义;
bash有内建的随机数生成器:$RANDOM
增强型赋值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=1
自增,自减:
let var+=1
let var++
let var-=1
let var--
练习1:写一个脚本
计算/etc/passwd文件中的第10个用户和第20用户的ID之和;
#!/bin/bash
userid1=$(head -n 10 /etc/passwd | tail -n 1 | cut -d: -f3)
userid2=$(head -n 20 /etc/passwd | tail -n 1 | cut -d: -f3)
useridsum=$[$userid1+$userid2]
echo "uid sum: $useridsum"
练习2:写一个脚本
传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和;
#!/bin/bash
spaceline1=$(grep "^[[:space:]]*$" $1 | wc -l)
spaceline2=$(grep "^[[:space:]]*$" $2 | wc -l)
echo "The sum of space line: $[$spaceline1+$spaceline2]"
bash的测试类型:
条件测试的表达式有3种:
1. [ expression ] 一定要有空格才行
例:#let A=3
#let B=6
#[ $A -eq $B ]
#echo $?
输出1 :所以0表示结果为真。
2. [[ expression ]] [[ $A -eq $B ]]
3. test expression test $A -eq $B
数值测试:
-eq: 测试两个整数是否相等; 比如 [ $A -eq $B ]
-ne: 测试两个整数是否不等;不等,为真;相等,为假;
-gt: 测试一个数是否大于另一个数;大于,为真;否则,为假;
-lt: 测试一个数是否小于另一个数;小于,为真;否则,为假;
-ge: 大于或等于
-le:小于或等于
字符串测试:
==:是否等于;
>: 是否大于;
<: 是否小于;
!=: 是否不等于;
=~: 左侧字符串是否能够被右侧的PATTERN所匹配;
Note: 此表达式一般用于[[ ]]中; [[ "$name" ~= ^O.* ]] 判断name这个变量的是否以O开头。
-z "STRING":测试字符串是否为空,空则为真,不空则为假;单目运算符
-n "STRING":测试字符串是否不空,不空则为真,空则为假;单目运算符
Note:用于字符串比较时用到的操作数都应该使用引号(单引号或者算引号要看是否需要变量替换);
文件测试
-e FILE:测试文件是否存在
-f FILE: 测试文件是否为普通文件
-d FILE: 测试指定路径是否为目录
-r FILE: 测试当前用户对指定文件是否有读取权限;
-w FILE: 测试当前用户对指定文件是否有写权限;
-x FILE: 测试当前用户对指定文件是否有执行权限;
例:[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
以上是关于bash特性的主要内容,如果未能解决你的问题,请参考以下文章