一、Shell alias:给命令创建别名
alisa 用来给命令创建一个别名。若直接输入该命令且不带任何参数,则列出当前 Shell 进程中使用了哪些别名。现在你应该能理解类似ll 这样的命令为什么与ls -l 的效果是一样的吧。
下面让我们来看一下有哪些命令被默认创建了别名:
[root@hecs-x-medium-2-linux-20211111093159 ~]
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
使用 alias 命令自定义别名的语法格式为:
alias new_name='command'
比如,一般的关机命令是shutdown-h now ,写起来比较长,这时可以重新定义一个关机命令,以后就方便多了。
alias myShutdown='shutdown -h now'
[root@hecs-x-medium-2-linux-20211111093159 ~]
再如,通过 date 命令可以获得当前的 UNIX 时间戳,具体写法为date +%s ,如果你嫌弃它太长或者不容易记住,那可以给它定义一个别名。
alias timestamp='date +%s'
例子:
[root@hecs-x-medium-2-linux-20211111093159 ~]
[root@hecs-x-medium-2-linux-20211111093159 ~]
1637581091
别名只是临时的
- 在代码中使用
alias 命令定义的别名只能在当前 Shell 进程中使用,在子进程和其它进程中都不能使用。当前 Shell 进程结束后,别名也随之消失。 - 要想让别名对所有的 Shell 进程都有效,就得把别名写入 Shell 配置文件。Shell 进程每次启动时都会执行配置文件中的代码做一些初始化工作,将别名放在配置文件中,那么每次启动进程都会定义这个别名。
二、Shell unalias命令:删除别名
使用 unalias 内建命令可以删除当前 Shell 进程中的别名。unalias 有两种使用方法:
- 第一种用法是在命令后跟上某个命令的别名,用于删除指定的别名。
- 第二种用法是在命令后接
-a 参数,删除当前 Shell 进程中所有的别名。
同样,这两种方法都是在当前 Shell 进程中生效的。要想永久删除配置文件中定义的别名,只能进入该文件手动删除。
[root@hecs-x-medium-2-linux-20211111093159 ~]
[root@hecs-x-medium-2-linux-20211111093159 ~]
-bash: timestamp: command not found
三、Shell echo命令:输出字符串
echo 是一个 Shell 内建命令,用来在终端输出字符串,并在最后默认加上换行符。请看下面的例子:
#!/bin/bash
name="zhangsan"
password="123456"
echo "${name}的密码是:${password}"
运行结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
zhangsan的密码是:123456
echo 命令输出结束后默认会换行,如果不希望换行,可以加上-n 参数,如下所示:
#!/bin/bash
name="Tom"
age=20
height=175
weight=62
echo -n "${name} is ${age} years old, "
echo -n "${height}cm in height "
echo "and ${weight}kg in weight."
echo "Thank you!"
运行结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
Tom is 20 years old, 175cm in height and 62kg in weight.
Thank you!
默认情况下,echo 不会解析以反斜杠\ 开头的转义字符。比如,\n 表示换行,echo 默认会将它作为普通字符对待。请看下面的例子:
[root@hecs-x-medium-2-linux-20211111093159 ~]
hello \nworld
我们可以添加-e 参数来让 echo 命令解析转义字符。例如:
[root@hecs-x-medium-2-linux-20211111093159 ~]
hello
world
有了-e 参数,我们也可以使用转义字符\c 来强制 echo 命令不换行了。请看下面的例子:
#!/bin/bash
name="Tom"
age=20
height=175
weight=62
echo -e "${name} is ${age} years old, \c"
echo -e "${height}cm in height \c"
echo "and ${weight}kg in weight."
echo "Thank you!"
运行结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
Tom is 20 years old, 175cm in height and 62kg in weight.
Thank you!
四、Shell read命令:读取从键盘输入的数据
read 是 Shell 内置命令,用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据。 read 命令的用法为:
read [-options] [variables]
选项 | 说明 |
---|
-a array | 把读取的数据赋值给数组 array,从下标 0 开始。 | -d delimiter | 用字符串 delimiter 指定读取结束的位置,而不是一个换行符(读取到的数据不包括 delimiter)。 | -e | 在获取用户输入的时候,对功能键进行编码转换,不会直接显式功能键对应的字符。 | -n num | 读取 num 个字符,而不是整行字符。 | -p prompt | 显示提示信息,提示内容为 prompt。 | -r | 原样读取(Raw mode),不把反斜杠字符解释为转义字符。 | -s | 静默模式(Silent mode),不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这是很有必要的。 | -t seconds | 设置超时时间,单位为秒。如果用户没有在指定时间内输入完成,那么 read 将会返回一个非 0 的退出状态,表示读取失败。 | -u fd | 使用文件描述符 fd 作为输入源,而不是标准输入,类似于重定向。 |
例子:
[root@hecs-x-medium-2-linux-20211111093159 ~]
hello.txt
[root@hecs-x-medium-2-linux-20211111093159 ~]
hello.txt
五、Shell exit命令:退出当前进程
exit 是一个 Shell 内置命令,用来退出当前 Shell 进程,并返回一个退出状态;使用$? 可以接收这个退出状态。
exit 命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0 。一般情况下,退出状态为 0 表示成功 ,退出状态为非 0 表示执行失败(出错 )了。 exit 退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
Shell 进程执行出错时,可以根据退出状态来判断具体出现了什么错误,比如打开一个文件时,我们可以指定 1 表示文件不存在,2 表示文件没有读取权限,3 表示文件类型不对。
#!/bin/bash
echo "befor exit"
exit 8
echo "after exit"
运行结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
befor exit
注意,exit 表示退出当前 Shell 进程,我们必须在新进程中运行 test.sh,否则当前 Shell 会话(终端窗口)会被关闭,我们就无法看到输出结果了。【前一篇博客说到 bash 命令是新开一个进程执行的】
七、Shell declare和typeset命令:设置变量属性
declare 和 typeset 都是 Shell 内建命令,它们的用法相同,都用来设置变量的属性。不过 typeset 已经被弃用了,建议使用 declare 代替。
declare 命令的用法如下所示:
declare [+/-] [aAfFgilprtux] [变量名=变量值]
其中,- 表示设置属性,+ 表示取消属性,aAfFgilprtux 都是具体的选项,它们的含义如下表所示:
选项 | 含义 |
---|
-f [name] | 列出之前由用户在脚本中定义的函数名称和函数体。 | -F [name] | 仅列出自定义函数名称。 | -g name | 在 Shell 函数内部创建全局变量。 | -p [name] | 显示指定变量的属性和值。 | -a name | 声明变量为普通数组。 | -A name | 声明变量为关联数组(支持索引下标为字符串)。 | -i name | 将变量定义为整数型。 | -r name[=value] | 将变量定义为只读(不可修改和删除),等价于 readonly name。 | -x name[=value] | 将变量设置为环境变量,等价于 export name[=value]。 |
【实例1】将变量声明为整数并进行计算。
#!/bin/bash
declare -i m n ret
m=10
n=30
ret=$m+$n
echo $ret
运行结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
40
八、Shell 数学计算(算术运算,加减乘除运算)
如果要执行算术运算(数学计算),就离不开各种运算符号,和其他编程语言类似,Shell 也有很多算术运算符,下面就给大家介绍一下常见的 Shell 算术运算符,如下表所示。
算术运算符 | 说明/含义 |
---|
+、- | 加法(或正号)、减法(或负号) | *、/、% | 乘法、除法、取余(取模) | ** | 幂运算 | ++、– | 自增和自减,可以放在变量的前面也可以放在变量的后面 | !、&&、|| | 逻辑非(取反)、逻辑与(and)、逻辑或(or) | <、<=、>、>= | 比较符号(小于、小于等于、大于、大于等于) | ==、!=、= | 比较符号(相等、不相等;对于字符串,= 也可以表示相当于) | <<、>> | 向左移位、向右移位 | ~、|、 &、^ | 按位取反、按位或、按位与、按位异或 | =、+=、-=、*=、/=、%= | 赋值运算符,例如 a+=1 相当于 a=a+1,a-=1 相当于 a=a-1 |
Shell 中常用的六种数学计算方式
运算操作符/运算命令 | 说明 |
---|
(( )) | 用于整数运算,效率很高,推荐使用。 | let | 用于整数运算,和 (()) 类似。 | $[] | 用于整数运算,不如 (()) 灵活。 | expr | 可用于整数运算,也可以处理字符串。比较麻烦,需要注意各种细节,不推荐使用。 | bc | Linux下的一个计算器程序,可以处理整数和小数。Shell 本身只支持整数运算,想计算小数就得使用 bc 这个外部的计算器。 | declare -i | 将变量定义为整数,然后再进行数学运算时就不会被当做字符串了。功能有限,仅支持最基本的数学运算(加减乘除和取余),不支持逻辑运算、自增自减等,所以在实际开发中很少使用。 |
1、Shell (()):对整数进行数学运算
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
注意:(( )) 只能进行整数运算,不能对小数(浮点数)或者字符串进行运算。后续讲到的 bc 命令可以用于小数运算。
双小括号 (( )) 的语法格式为:((表达式))
(( )) 的用法如下:
运算操作符/运算命令 | 说明 |
---|
((a=10+66))((b=a-15)) ((c=a+b)) | 这种写法可以在计算完成后给变量赋值。以 ((b=a-15)) 为例,即将 a-15 的运算结果赋值给变量 c。 注意,使用变量时不用加$ 前缀,(( )) 会自动解析变量名。 | a=
(
(
10
+
66
)
b
=
((10+66) b=
((10+66)b=((a-15)) c=$((a+b)) | 可以在 (( )) 前面加上$ 符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=
(
(
a
+
b
)
)
为
例
,
即
将
a
+
b
这
个
表
达
式
的
运
算
结
果
赋
值
给
变
量
c
。
注
意
,
类
似
c
=
(
(
a
+
b
)
)
这
样
的
写
法
是
错
误
的
,
不
加
‘
((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。 注意,类似 c=((a+b)) 这样的写法是错误的,不加`
((a+b))为例,即将a+b这个表达式的运算结果赋值给变量c。注意,类似c=((a+b))这样的写法是错误的,不加‘`就不能取得表达式的结果。 | ((a>7 && b==c)) | (( )) 也可以进行逻辑运算,在 if 语句中常会使用逻辑运算。 | echo $((a+10)) | 需要立即输出表达式的运算结果时,可以在 (( )) 前面加$ 符号。 | ((a=3+5, b=a+10)) | 对多个表达式同时进行计算。 |
2、Shell let命令:对整数进行数学运算
给变量 i 加 8:
[root@hecs-x-medium-2-linux-20211111093159 ~]
[root@hecs-x-medium-2-linux-20211111093159 ~]
[root@hecs-x-medium-2-linux-20211111093159 ~]
10
let i+=8 等同于 ((i+=8)),但后者效率更高。
let 后面可以跟多个表达式:
[root@hecs-x-medium-2-linux-20211111093159 ~]
[root@hecs-x-medium-2-linux-20211111093159 ~]
[root@hecs-x-medium-2-linux-20211111093159 ~]
11 30
3、Shell bc 命令【计算器命令】
一般情况下,我们使用不带任何参数的bc 命令。 如果需要bc 不输出提示信息,可以加上-q 参数: bc -q
如果要使用强大的数学库,比如计算三角函数,需要加上-l 参数:bc -l
因为 bc 本身是一个命令解释器,要退出它只要直接输入 quit 回车 或者 按 Ctrl+D 终止。
[root@hecs-x-medium-2-linux-20211111093159 ~]
(standard_in) 1: syntax error
[root@hecs-x-medium-2-linux-20211111093159 ~]
12
[root@hecs-x-medium-2-linux-20211111093159 ~]
3.1415929
[root@hecs-x-medium-2-linux-20211111093159 ~]
65535
[root@hecs-x-medium-2-linux-20211111093159 ~]
3E8
123*321
123/321
scale=4;123/321
[root@hecs-x-medium-2-linux-20211111093159 ~]
123*321
123/321
scale=4;123/321
[root@hecs-x-medium-2-linux-20211111093159 ~]
39483
0
.3831
#!/bin/bash
echo -n "Enter base of a triangle : "
read b
echo -n "Enter height of a triangle : "
read h
area=$(echo "scale=2;(1/2) * $b * $h"|bc)
echo "Area of a triangle is $area"
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
Enter base of a triangle : 60
Enter height of a triangle : 100
Area of a triangle is 3000.00
[root@hecs-x-medium-2-linux-20211111093159 ~]
Runtime error (func=(main), adr=11): Function a not defined.
[root@hecs-x-medium-2-linux-20211111093159 ~]
3.141592653589793238462643383279502884197169399375105820974944592307\
8164062862089986280348253421170676
九、Shell test 指令
1、与文件检测相关的 test 选项
文件类型判断 | |
---|
选 项 | 作 用 | -b filename | 判断文件是否存在,并且是否为块设备文件。 | -c filename | 判断文件是否存在,并且是否为字符设备文件。 | -d filename | 判断文件是否存在,并且是否为目录文件。 | -e filename | 判断文件是否存在。 | -f filename | 判断文件是否存在,井且是否为普通文件。 | -L filename | 判断文件是否存在,并且是否为符号链接文件。 | -p filename | 判断文件是否存在,并且是否为管道文件。 | -s filename | 判断文件是否存在,并且是否为非空。 | -S filename | 判断该文件是否存在,并且是否为套接字文件。 | 文件权限判断 | | 选 项 | 作 用 | -r filename | 判断文件是否存在,并且是否拥有读权限。 | -w filename | 判断文件是否存在,并且是否拥有写权限。 | -x filename | 判断文件是否存在,并且是否拥有执行权限。 | -u filename | 判断文件是否存在,并且是否拥有 SUID 权限。 | -g filename | 判断文件是否存在,并且是否拥有 SGID 权限。 | -k filename | 判断该文件是否存在,并且是否拥有 SBIT 权限。 | 文件比较 | | 选 项 | 作 用 | filename1 -nt filename2 | 判断 filename1 的修改时间是否比 filename2 的新。 | filename -ot filename2 | 判断 filename1 的修改时间是否比 filename2 的旧。 | filename1 -ef filename2 | 判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法 |
举例:
#!/bin/bash
read -p "输入内容输入文件名称:" filename
read -p "输入内容:" url
if test -w $filename && test -n $url;
then
echo $url > $filename
echo "写入成功"
else
echo "写入失败"
fi
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
输入内容输入文件:helloworld.sh
输入写入内容:log.txt
写入成功
[root@hecs-x-medium-2-linux-20211111093159 ~]
log.txt
2、与数值比较相关的 test 选项
选 项 | 作 用 |
---|
num1 -eq num2 | 判断 num1 是否和 num2 相等。 | num1 -ne num2 | 判断 num1 是否和 num2 不相等。 | num1 -gt num2 | 判断 num1 是否大于 num2 。 | num1 -lt num2 | 判断 num1 是否小于 num2。 | num1 -ge num2 | 判断 num1 是否大于等于 num2。 | num1 -le num2 | 判断 num1 是否小于等于 num2。 |
注意,test 只能用来比较整数,小数相关的比较还得依赖 bc 命令【计算器命令】。
Shell test 数值比较举例:
#!/bin/bash
read a b
if test $a -eq $b;
then
echo "两个数相等"
else
echo "两个数不相等"
fi
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
10 20
两个数不相等
[root@hecs-x-medium-2-linux-20211111093159 ~]
10 10
两个数相等
3、与字符串判断相关的 test 选项
选 项 | 作 用 |
---|
-z str | 判断字符串 str 是否为空。 | -n str | 判断宇符串 str 是否为非空。 | str1 = str2 str1 == str2 | = 和== 是等价的,都用来判断 str1 是否和 str2 相等。 | str1 != str2 | 判断 str1 是否和 str2 不相等。 | str1 > str2 | 判断 str1 是否大于 str2。\> 是> 的转义字符,这样写是为了防止> 被误认为成重定向运算符。 | str1 < str2 | 判断 str1 是否小于 str2。同样,\< 也是转义字符。 |
举例:
#!/bin/bash
read str1
read str2
if [ -z "$str1" ] || [ -z "$str2" ];
then
echo "字符串不能为空"
exit 0
fi
if [ $str1 = $str2 ];
then
echo "两个字符串相等"
else
echo "两个字符串不相等"
fi
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
yyyd
jsjj
两个字符串不相等
[root@hecs-x-medium-2-linux-20211111093159 ~]
jjj
字符串不能为空
4、与逻辑运算相关的 test 选项
选 项 | 作 用 |
---|
expression1 -a expression | 逻辑与,表达式 expression1 和 expression2 都成立,最终的结果才是成立的。 | expression1 -o expression2 | 逻辑或,表达式 expression1 和 expression2 有一个成立,最终的结果就成立。 | !expression | 逻辑非,对 expression 进行取反。 |
例子:
#!/bin/bash
read str1
read str2
if [ -z "$str1" -o -z "$str2" ];
then
echo "字符串不能为空"
exit 0
fi
if [ $str1 = $str2 ];
then
echo "两个字符串相等"
else
echo "两个字符串不相等"
fi
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
yyyd
jsjj
两个字符串不相等
[root@hecs-x-medium-2-linux-20211111093159 ~]
jjj
字符串不能为空
当你在 test 命令中使用变量时,我强烈建议将变量用双引号"" 包围起来。
注意点:
- test 命令比较奇葩,
>、<、== 只能用来比较字符串,不能用来比较数字,比较数字需要使用 -eq、-gt 等选项;不管是比较字符串还是数字,test 都不支持 >= 和 <=。 - 对于整型数字的比较,我建议大家使用
(()) 。
十、 Shell [[]] 关键字详解:检测某个条件是否成立
[[ ]] 是 Shell 内置关键字,它和 test 命令 类似,也用来检测某个条件是否成立。
test 能做到的,[[ ]] 也能做到,而且 [[ ]] 做的更好;test 做不到的,[[ ]] 还能做到。可以认为 [[ ]] 是 test 的升级版,对细节进行了优化,并且扩展了一些功能。
- [[ ]] 的用法为:[[ expression ]]
当 [[ ]] 判断 expression 成立时,退出状态为 0,否则为非 0 值。注意[[ ]] 和expression 之间的空格,这两个空格是必须的,否则会导致语法错误。
[[ ]] 是 Shell 内置关键字,不是命令,在使用时没有给函数传递参数的过程,所以 test 命令的某些注意事项在 [[ ]] 中就不存在了,具体包括:
- 不需要把变量名用双引号
"" 包围起来,即使变量是空值,也不会出错。 - 不需要、也不能对 >、< 进行转义,转义后会出错。
- 注意,[[ ]] 剔除了 test 命令的
-o 和-a 选项,你只能使用 || 和 &&。
例子:
#!/bin/bash
read str1
read str2
if [[ -z $str1 ]] || [[ -z $str2 ]];
then
echo "字符串不能为空"
elif [[ $str1 < $str2 ]];
then
echo "str1 < str2"
else
echo "str1 >= str2"
fi
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
yysyd
hshd
str1 >= str2
[root@hecs-x-medium-2-linux-20211111093159 ~]
shahd
字符串不能为空
[root@hecs-x-medium-2-linux-20211111093159 ~]
yyy
yyyy
str1 < str2
总结:
test 或 [] | [[ ]] | | |
---|
[ -z “
s
t
r
1
"
]
∥
∥
[
?
z
"
str1" ] \|\| [ -z "
str1"]∥∥[?z"str2” ] | √ | [[ -z $str1 ]] || [[ -z $str2 ]] | √ | [ -z “
s
t
r
1
"
?
o
?
z
"
str1" -o -z "
str1"?o?z"str2” ] | √ | [[ -z $str1 -o -z $str2 ]] | × | [ -z $str1 || -z $str2 ] | × | [[ -z $str1 || -z $str2 ]] | √ |
在 Shell [[ ]] 中,可以使用=~ 来检测字符串是否符合某个正则表达式,它的用法为:[[ str =~ regex ]]
#!/bin/bash
read tel
if [[ $tel =~ ^1[0-9]{10}$ ]];
then
echo "你输入的是手机号码"
else
echo "你输入的不是手机号码"
fi
测试结果:
[root@hecs-x-medium-2-linux-20211111093159 ~]
2132172321
你输入的不是手机号码
[root@hecs-x-medium-2-linux-20211111093159 ~]
17787727711
你输入的是手机号码
对^1[0-9]{10}$ 的说明:
^ 匹配字符串的开头(一个位置);[0-9]{10} 匹配连续的十个数字;$ 匹配字符串的末尾(一个位置);
最后: [[ ]] 对数字的比较仍然不友好,所以我建议,以后大家使用 if 判断条件时,用 (()) 来处理整型数字,用 [[ ]] 来处理字符串或者文件。
文章内容参考:http://m.biancheng.net/view/942.html
|