Shell中引号的使用
Shell中支持的引号:””(双引号)、’’(单引号)、··(反引号)
单引号与双引号
作用:将字符串作为一个整体。
如我们创建文件时:
#不使用引号时,将创建3个文件
[root@localhost test]# touch a b c
[root@localhost test]# ls -l
total 0
-rw-r--r-- 1 root root 0 Aug 31 09:57 a
-rw-r--r-- 1 root root 0 Aug 31 09:57 b
-rw-r--r-- 1 root root 0 Aug 31 09:57 c
#使用引号则将a b c作为一个文件的文件名
[root@localhost test]# touch "a b c"
[root@localhost test]# ls -l
total 0
-rw-r--r-- 1 root root 0 Aug 31 09:57 a
-rw-r--r-- 1 root root 0 Aug 31 09:57 a b c
-rw-r--r-- 1 root root 0 Aug 31 09:57 b
-rw-r--r-- 1 root root 0 Aug 31 09:57 c
双引号与单引号的区别:
单引号可以屏蔽特殊符号,将特殊符号的特殊含义屏蔽,转化为字符表面的含义,不能解析变量。
# ‘#’号在Shell中为单行注释的标志,直接echo输出则#及后面的内容不会被执行
[root@localhost test]# echo #lsk
[root@localhost test]# echo "#ls"
#ls
[root@localhost test]# echo '#ls'
#ls
# 定义变量,直接echo输出及使用双引号,变量将被解析,使用单引号不能解析
[root@localhost test]# test="Hello World"
[root@localhost test]# echo $test
Hello World
[root@localhost test]# echo "$test"
Hello World
[root@localhost test]# echo '$test'
$test
# 使用\将$符进行转义,$转移为普通字符
[root@localhost test]# echo "\$test"
$test
[root@localhost test]# echo \$test
$test
反引号
反引号是一个命令替换符号,它可以使用命令的输出结果替代命令。
# 使用反引号将date命令的输出结果作为备份文件名的一部分
[root@localhost test]# tar -zcf log-`date +"%Y-%d-%m"`.tar.gz /var/log/
[root@localhost test]# ls
a a b c b c log-2021-31-08.tar.gz
# 使用反引号将统计登录系统账户数作为值赋给变量
[root@localhost test]# userTotal=`who | wc -l`
[root@localhost test]# echo $userTotal
2
$()组合符号与反引号的功能相同
[root@localhost test]# echo "当前系统账户登录数量为:$(who | wc -l)"
当前系统账户登录数量为:2
[root@localhost test]# echo "当前系统账户登录数量为:$(who | wc -l)"
当前系统账户登录数量为:2
[root@localhost test]# ping -c2 $(hostname)
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.015 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.039 ms
--- localhost ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.015/0.027/0.039/0.012 ms
Shell变量
Shell中变量的类型有:
- 自定义变量:用户自主设置的变量
- 环境变量:变量名通常大写,有操作系统维护
- 位置变量:bash内置变量,存储脚本执行时的参数
- 预定义变量:bash内置变量,可以调用但是不能修改
自定义变量
用户自定义变量时,变量名的规则:变量名仅可以使用字母、数字和下划线组合,但是不能以数字开头。在实际定义时最好使用比较容易理解的单词或拼音,切记不要使用随意的字符作为变量名,没有规律的变量名会让脚本的可阅读性变得极差。
定义变量格式:变量名=变量值
取消变量:unset 变量名
注意:=号两边不能有空格,不要使用关键字作为变量名,如:ls、cd等
# 定义变量时=号两边有空格时将报错
[root@localhost test]# var ="value"
-bash: var: command not found
[root@localhost test]# var= "value"
-bash: value: command not found
[root@localhost test]# var = "value"
-bash: var: command not found
# 自定义变量
[root@localhost test]# var="value"
# 输出变量
[root@localhost test]# echo $var
value
# 取消变量
[root@localhost test]# unset var
[root@localhost test]# echo $var
[root@localhost test]#
当输出变量时,变量名后面直接跟其他字母、数字或下划线时,需要使用{}将变量名括起来。
[root@localhost test]# money=999
[root@localhost test]# echo $money
999
#变量名后直接跟字母将无任何输出,moneyRMB将作为整个变量名,未定义
[root@localhost test]# echo $moneyRMB
# 使用{}分隔变量名及其他字符
[root@localhost test]# echo ${money}RMB
999RMB
[root@localhost test]# echo $money_RMB
[root@localhost test]# echo $money12RMB
[root@localhost test]# echo ${money}12RMB
99912RMB
[root@localhost test]# echo ${money}_RMB
999_RMB
[root@localhost test]# echo $money:RMB
999:RMB
[root@localhost test]# echo $money-RMB
999-RMB
环境变量
环境变量一般存储在/etc/profile或~/.bash_profile中,可以使用命令env查看所有环境变量。
常用的环境变量有:
- PATH:系统环境变量路径
- PWD:用户当前工作目录
- USER:当前登录系统的用户名
- UID:当前账号的UID
- HOME:当前用户的家目录
- SHELL:当前用户的SHEEL解释器
- RANDOM:返回0~32767之间的随机整数
位置变量
位置变量是存储脚本执行时的参数,使用$n表示,n为整数序列,n大于9是整数需使用{}号分隔,如:$1、$2...${11}、${12}...
[root@localhost test]# vim test.sh
#!/bin/bash
# 接收并输出位置变量
echo $1
echo $2
echo $2
[root@localhost test]# chmod +x test.sh
[root@localhost test]# ./test.sh 11 22 33
11
22
22
预定义变量
预定义变量用来保存脚本程序的执行信息。可以直接使用,但是不能修改及赋值。
常见的预定义变量表:
变量名 | 描述 |
$0 | 返回当前命令的名称 |
$# | 返回命令参数的个数 |
$* | 返回命令行的所有参数,“$*”所有参数作为一个整体 |
$@ | 返回命令行的所有参数,“$@”所有参数作为独立的个体 |
$? | 返回上一条命令退出时的状态码(一般0表示执行成功,非0表示执行失败) |
$$ | 返回当前进程的进程号 |
$! | 返回最后一个后台进程的进程号 |
[root@localhost test]# vim sys_var.sh
#!/bin/bash
echo "当前脚本的名称为:"$0
echo "当前脚本的第1个参数为:"$1
echo "当前脚本的第2个参数为:"$2
echo "当前脚本的第3个参数为:"$3
echo "当前脚本的所有参数为:"$*
echo "创建一个文件..."
# 所有参数将作为一个整体,创建一个以所有参数为名称的文件
touch "$*"
echo "创建多个文件..."
# 所有参数作为独立的个体,创建以每个参数为名称的多个文件
touch "$@"
ls /etc/passwd
echo "执行成功的返回状态码:$?"
ls /abcd
echo "执行失败的返回状态码:$?"
echo "当前进程的进程号:"$$
echo "最后一个后台进程的进程号:"$!
[root@localhost test]# bash sys_var.sh A B C D 3
当前脚本的名称为:sys_var.sh
当前脚本的第1个参数为:A
当前脚本的第2个参数为:B
当前脚本的第3个参数为:C
当前脚本的所有参数为:A B C D 3
创建一个文件...
创建多个文件...
/etc/passwd
执行成功的返回状态码:0
ls: cannot access /abcd: No such file or directory
执行失败的返回状态码:2
当前进程的进程号:3701
最后一个后台进程的进程号:
[root@localhost test]# ll
total 536
-rw-r--r-- 1 root root 0 Aug 31 11:18 3
-rw-r--r-- 1 root root 0 Aug 31 09:57 a
-rw-r--r-- 1 root root 0 Aug 31 11:18 A
-rw-r--r-- 1 root root 0 Aug 31 09:57 a b c
-rw-r--r-- 1 root root 0 Aug 31 11:18 A B C D 3
-rw-r--r-- 1 root root 0 Aug 31 09:57 b
-rw-r--r-- 1 root root 0 Aug 31 11:18 B
-rw-r--r-- 1 root root 0 Aug 31 09:57 c
-rw-r--r-- 1 root root 0 Aug 31 11:18 C
-rw-r--r-- 1 root root 0 Aug 31 11:18 D
-rw-r--r-- 1 root root 540239 Aug 31 10:15 log-2021-31-08.tar.gz
-rw-r--r-- 1 root root 503 Aug 31 11:17 sys_var.sh
-rwxr-xr-x 1 root root 67 Aug 31 11:01 test.sh
变量的作用范围
局部变量
只在当前Shell环境中有效,无法在子shell环境中使用。
# 当前Shell中定义变量var,只在当前shell环境中有效
[root@localhost test]# var="test"
[root@localhost test]# echo $var
test
# 进入子shell环境中,变量无法使用
[root@localhost test]# sh
sh-4.2# echo $var
sh-4.2# exit
exit
[root@localhost test]# echo $var
test
全局变量
在当前Shell及子shell中均有效。
使用export定义全局变量
[root@localhost test]# export var="test1"
[root@localhost test]# echo $var
test1
[root@localhost test]# sh
sh-4.2# echo $var
test1
sh-4.2# sh
sh-4.2# echo $var
test1
sh-4.2# exit
exit
sh-4.2# echo $var
test1
sh-4.2# exit
exit
[root@localhost test]# echo $var
test1
数据过滤与正则表达式
数据过滤
grep命令
grep命令可以查找关键词并打印匹配的行。
语法格式:
grep [选项] 匹配模式 [文件]
常用命令选项:
- -i:不区分字母带小写
- -v:取反匹配
- -w:匹配单词
- -q:静默匹配,不将结果显示在屏幕上
- -E:使用扩展正则匹配
- -P:使用Perl兼容正则匹配
[root@localhost test]# vim test.txt
Hello The World!
Other men live to eat, while I eat to live.
It is never too late to mend.
[root@localhost test]# grep The test.txt
Hello The World!
[root@localhost test]# grep the test.txt
Other men live to eat, while I eat to live.
[root@localhost test]# grep -i the test.txt
Hello The World!
Other men live to eat, while I eat to live.
[root@localhost test]# grep -vi the test.txt
It is never too late to mend.
[root@localhost test]# grep -wi the test.txt
Hello The World!
[root@localhost test]# grep -qi the test.txt
egrep命令
使用扩展正则匹配过滤数据
# 匹配0出现至少2次,最多3次的行
[root@localhost test]# egrep "0{2,3}" passwd
games:x:12:100:games:/usr/games:/sbin/nologin
正则表达式
基本正则表达式(Basic Regular Expression)
基本正则符号及含义:
正则符号 | 含义 |
c | 匹配字母c |
. | 匹配任意单个字符 |
* | 匹配前一个字符出现0次或多次 |
.* | 匹配多个任意字符 |
[集合] | 匹配集合中的任意单个字符 |
[^集合] | 对集合取反 |
^ | 匹配字符串的开头 |
$ | 匹配字符串的结尾 |
\ | 匹配转义后的字符 |
\{m,n\} | 匹配前一个字符m到n次 |
\{m,\} | 匹配前一个字符至少m次 |
\{m\} | 匹配前一个字符重复m次 |
# 拷贝passwd文件到当前目录
[root@localhost test]# cp /etc/passwd ./
# 查找有root的行
[root@localhost test]# grep root passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
# 查找:与0:之间有两个任意字符的行
[root@localhost test]# grep ":..0:" passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
...
# 查找至少有一个0的行
[root@localhost test]# grep "00*" passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
...
# 查找包含oot或ost的行
[root@localhost test]# grep "o[os]t" passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
# 查找包含数字的行
[root@localhost test]# grep "[0-9]" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
# 查找包含f-q小写字母的行
[root@localhost test]# grep "[f-q]" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
...
# 查找以root开头的行
[root@localhost test]# grep "^root" passwd
root:x:0:0:root:/root:/bin/bash
# 查找以bash结尾的行
[root@localhost test]# grep "bash$" passwd
root:x:0:0:root:/root:/bin/bash
test:x:1001:1001::/home/test:/bin/bash
# 查找sbin后面不是n的行
[root@localhost test]# grep "sbin[^n]" passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...
# 查找数字0出现至少一次,最多2次的行
[root@localhost test]# grep "0\{1,2\}" passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
...
# 查找两个root之间可以是任意字符的行
[root@localhost test]# grep "\(root\).*\1" passwd
root:x:0:0:root:/root:/bin/bash
# 查找空白行
[root@localhost test]# grep "^$" passwd
# 查找非空白行
[root@localhost test]# grep -v "^$" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
扩展正则表达式(Extended Regular Expression)
扩展正则表达式及其含义
正则符号 | 含义 |
{m,n} | 等同于基本正则的\{m,n\} |
+ | 匹配前面的字符出现一次或多次 |
? | 匹配前面的字符出现0次或1次 |
| | 匹配逻辑或 |
() | 匹配正字集合,同时也有保留的意思 |
{m,} | 等同于基本正则的\{m,\} |
{m} | 等同于基本正则的\{m\} |
grep 使用扩展正则需要使用-E选项
[root@localhost test]# grep -E "0{2,3}" passwd
games:x:12:100:games:/usr/games:/sbin/nologin
[root@localhost test]# grep -E "root|test" passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
test:x:1001:1001::/home/test:/bin/bash
POSIX规范的正则表达式
POSIX正则表达式规范可以帮助我们解决语系的问题,并且POSIX规范的正则表达式也比较接近于自然语言。
POSIX规范字符集
字符集 | 含义 | 字符集 | 含义 |
[:alpha:] | 字母字符 | [:graph:] | 非空格字符 |
[:alnum:] | 字母与数字字符 | [:print:] | 任意可以显示的字符 |
[:cntrl:] | 控制字符 | [:space:] | 任意可以产生空白的字符 |
[:digit:] | 数字字符 | [:blank:] | 空格与Tab键字符 |
[:xdigit:] | 十六进制数字字符 | [:lower:] | 小写字符 |
[:punct:] | 标点符号 | [:upper:] | 大写字符 |
root@localhost test]# grep "[[:punct:]]" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost test]# grep "[[:alnum:]]" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
Perl兼容正则表达式
Perl兼容的正则符号
符号 | 含义 |
\b | 匹配单词边界 |
\B | 和\b相反 |
\w | 匹配字母数字下划线 |
\W | 和\w相反 |
\s | 匹配空白 |
\d | 匹配数字 |
\D | 匹配非数字 |
grep使用Perl兼容的正则表达式过滤数据,需要使用-P选项
[root@localhost test]# grep "sh" passwd
root:x:0:0:root:/root:/bin/bash
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
wangyh:x:1000:1000::/home/wangyh:/bin/bash
test:x:1001:1001::/home/test:/bin/bash
[root@localhost test]# grep -P "sh\b" passwd
root:x:0:0:root:/root:/bin/bash
wangyh:x:1000:1000::/home/wangyh:/bin/bash
test:x:1001:1001::/home/test:/bin/bash
[root@localhost test]# grep -P "\w" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@localhost test]# grep -P "\W" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
算术运算
整数运算
语法格式:
- $((表达式))
- $[表达式]
- let 表达式
注:上述命令无法执行小数的运算
常用的运算符号
运算符号 | 含义描述 |
++ | 自加1 |
-- | 自减1 |
+、-、*、/ | 加、减、乘、除 |
** | 求幂 |
% | 取余 |
+= | 自加任意数 |
-= | 自减任意数 |
*= | 自乘任意数 |
/= | 自除任意数 |
%= | 对任意数取余 |
&& | 逻辑与 |
|| | 逻辑或 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
表达式1?表达式2:表达式3 | 若表达式1成立则执行表达式2,否则执行表达式3 |
[root@localhost test]# echo $((8+3))
11
[root@localhost test]# echo $((8-3))
5
[root@localhost test]# echo $((8*3))
24
[root@localhost test]# echo $((8/3))
2
[root@localhost test]# echo $((8%3))
2
[root@localhost test]# echo $((8**3))
512
[root@localhost test]# i=1
[root@localhost test]# echo $((i++))
1
[root@localhost test]# echo $i
2
[root@localhost test]# echo $((++i))
3
[root@localhost test]# echo $i
3
[root@localhost test]# echo $((i--))
3
[root@localhost test]# echo $i
2
[root@localhost test]# echo $((--i))
1
[root@localhost test]# echo $i
1
[root@localhost test]# echo $[i+=5]
6
[root@localhost test]# echo $[i-=2]
4
[root@localhost test]# echo $[i*=3]
12
[root@localhost test]# echo $[i/=4]
3
[root@localhost test]# echo $[i%=2]
1
[root@localhost test]# echo $[i**=2]
[root@localhost test]# echo $[3>2 && 3> 1]
1
[root@localhost test]# echo $[3>2 && 3> 4]
0
[root@localhost test]# echo $[3>2 || 3> 4]
1
[root@localhost test]# echo $[3>5 || 3> 4]
0
[root@localhost test]# x=2;y=3
[root@localhost test]# echo $[x > 3 ? x : y]
3
[root@localhost test]# echo $[x < 3 ? x : y]
2
使用let命令计算时,默认不会输出计算的结果,一般需要将运算的结果赋值给变量,通过变量查看运算的结果。另外使用let运算时,不需要在变量名前加$符号。
[root@localhost test]# x=5;y=8
[root@localhost test]# let z=x+y
[root@localhost test]# echo $z
13
[root@localhost test]# let m=x*y
[root@localhost test]# echo $m
40
bc命令
bc命令支持交互式和非交互式两种方式。
交互模式下:
非交互模式下:
[root@localhost test]# echo "3.4 + 5.88" | bc
9.28
[root@localhost test]# echo "3.4 * 5.88" | bc
19.99
使用scale可以指定输出小数的位数:
[root@localhost test]# echo "scale=2;837/32" | bc
26.15
[root@localhost test]# echo "scale=3;837/32" | bc
26.156
[root@localhost test]# echo "scale=4;837/32" | bc
26.1562
另外,bc命令也可以使用内置变量ibase(in)和obase(out)进行进制转换。
ibase:指定输入数字的进制
obase:指定输出数字的进制
# 输入二进制的1110,输出十进制的14
[root@localhost test]# echo "ibase=2;1110" | bc
14
# 输入十进制的10,输出二进制的1010
[root@localhost test]# echo "obase=2;10" | bc
1010
# 输入十六进制的FF,输出十进制的255
[root@localhost test]# echo "ibase=16;FF" | bc
255