解释器
解释器种类文件:/etc/shells
ksh(较老版本解释器) sh(无颜色)
修改方式:
- 修改登陆shell:
[root@localhost ~]# usermod -s /bin/rsh root #修改解释器
- /etc/passwd #配置文件修改
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# echo $0 #查看当前使用的shell
基础操作
常见快捷键:
快捷键 | 功能 | 快捷键 | 功能 | 快捷键 | 功能 | 快捷键 | 功能 |
---|---|---|---|---|---|---|---|
ctrl+A | 至首 | ctrl+E | 至尾 | ctrl+C | 终止 | ctrl+q | 显示输入 |
ctrl+M | Enter | ctrl+U | 删除到首 | ctrl+w | 删除前一个单词 | ctrl+s | 隐藏输入 |
alt+“.” | 上一命令最后一个单词 | ctrl+D | 退出 | tab | 补全(软件包:bash-completion) |
历史记录:history
配置文件: /etc/profile
HISTSIZE=1000
[root@localhost ~]# history |wc -l #查看当前历史命令总数
[root@localhost ~]# !10 #执行第10条
[root@localhost ~]# !cat #执行最近一条以cat开头的命令
[root@localhost ~]# history -c #清空历史命令缓存
[root@localhost ~]# >/root/.bash_history #置空历史命令存储文件
重定向输出:
- 标准输入(stdin),描述号为0
- 标准输出(stdout),描述号为1
- 标准错误(stderr),描述号为2
管道操作:
[root@localhost ~]# ls -l /etc/ |wc -l #查看/etc/中文件给wc -l统计数量
脚本的执行:
[root@localhost ~]# bash abc #无需执行权限
[root@localhost ~]# . abc #无需执行权限,等同于source
[root@localhost ~]# source abc #无需执行权限
[root@localhost ~]# ./abc #需执行权限
[root@localhost ~]# /opt/abc #需执行权限
变量:
[root@localhost ~]# env #列出所有环境变量
[root@localhost ~]# set #列出所有变量
[root@localhost ~]# test=11 #自定义变量
[root@localhost ~]# echo ${test)RMB #{}将变量和其他字符区分开
[root@localhost ~]# unset test #取消设置
环境变量:
变量名 | 变量意义 | 变量名 | 变量意义 |
---|---|---|---|
$USER | 当前用户名 | $HOME | 当前用户家目录 |
$SHELL | 登陆shell | $PATH | 命令路径 |
$PS1 | [root@server0 ~]# | $PS2 | >(换行显示符) |
位置变量与预定义变量:
变量名 | 变量意义 | 变量名 | 变量意义 |
---|---|---|---|
$0 | 脚本名 | $! | 最后一个进程的pid |
$1 | 位置变量1 | $* | 所有位置变量值 |
$1 | 位置变量1 | $* | 所有位置变量值 |
$2 | 位置变量2 | $# | 位置变量数量 |
$3 | 位置变量3 | $? | 状态值 |
$$ | 当前脚本pid号 |
" ":将有内容作为整体
' ':同" ",并且取消其中特殊符号的特殊含义
` `或$( ):将其中的命令执行的结果作为字符串存储
read:等待并接收用户输入并赋值给变量:
[root@localhost ~]# read -p "请输入一个整数:" num #回车后输入10
[root@localhost ~]# echo $i #输出结果为10
stty -echo 显示控制:
[root@localhost ~]# vi a.sh
#!/bin/bash
read -p "请输入用户名" name
stty -echo #关闭回显
read -p "请输入密码:" pass
stty echo #开启回显
echo " " #恢复回显后补一个空行
export:发布全局变量到子解释器
[root@localhost ~]# yy=11
[root@localhost ~]# export yy #发布已定义变量
[root@localhost ~]# export xx="1234" #发布新变量
整数运算:
基本运算:四则运算
加 num1 + num2 减 num1 - num2
乘 num1 * num2 除 num1 / num2
求模 num1 % num2 #求两者相除的余数
1.expr工具:(数字间空格隔开,乘号用*转义,避免被当做通配符)
[root@localhost ~]# expr 43 + 21
[root@localhost ~]# expr $x + $y
2.$[ ]算式转换为结果
格式:echo $[num1+num2]
乘法*无需转义,运算符两侧可以无空格
其中变量可以省略$
计算结果替换表达式本身
[root@localhost ~]# x=43
[root@localhost ~]# echo $[x+21],$((x*21))
64,903
3.let运算:
变量自增/减操作:$[ ]替换,或let命令完成
简写表达式 | 完整表达式 |
---|---|
i++ | i=i+1 |
i– | i=i-1 |
i+=2 | i=i+2 |
i*=2 | i=i*2 |
i/=2 | i=i/2 |
i%2 | i=i%2 |
[root@localhost ~]# i=43
[root@localhost ~]# echo $[i+=2]
45
[root@localhost ~]# echo $[i-=8]
37
[root@localhost ~]# let i++;echo $i
38
[root@localhost ~]# let i-=7;echo $i
31
4.小数运算:
bc:小数运算工具(交互式)
[root@localhost ~]# bc
scale=4 #精确到小数点后4位
12.34*56.78
700.6652 #quit退出
5.结合管道实现非交互式:
[root@localhost ~]# a=1.11;b=2.22
[root@localhost ~]# echo "$a+$b" |bc #单表达式
[root@localhost ~]# echo "scale=4;$a*$b;5/3" |bc #多表达式
6.bc小数值比较:
表达式成立,返回值1,否则为0
常见比较:>,>=,<,<=,==,!=
[root@localhost ~]# a=12.34;b=56.78
[root@localhost ~]# echo "$a<=$b" |bc #a是否小于或等于b
1
[root@localhost ~]# echo "$a>$b" |bc #a是否大于b
0
判断:
test判断:
格式:1.test 选项 参数 2.[ 选项 参数 ]
1.比较字符串:
[root@localhost ~]# [ -z "" ] #判断""中字符串是否为空,空则成立
[root@localhost ~]# [ -n "" ] #判断""中字符串不为空,不为空则成立
[root@localhost ~]# [ $USER == "root" ] &&echo yes ||echo no
yes #[ ]内成立返回值为0,执行&&后的命令
[root@localhost ~]# [ $USER == "tom" ] &&echo yes ||echo no
no #[ ]内不成立返回值非0,执行||后的命令
2.比较整数大小:
比较符 含义
-eq 等于equal
-ne 不等于not equal
-ge 大于等于greater or equal
-le 小于等于lesser or equal
-gt 大于greater than
-lt 小于lesser than
[root@localhost ~]# who |wc -l -->2
[root@localhost ~]# [ $(who(wc -l) -le 5 ] &&echo 'ok'
ok
3.&&和||:
&&echo ok:之前最后执行命令并成功,则执行echo ok
||echo ok:之前最后执行命令并失败,则执行echo ok
4.测试文件状态: [ 比较符 文件或目录 ]
比较符 含义
-e 判断是否存在,存在为真,返回值为0
-d 存在且为目录为真
-f 存在且为文件为真
-r 有可读权限为真
-w 有可写权限为真
-x 有可执行权限为真
[root@localhost ~]# [ -d /etc/passwd ]
[root@localhost ~]# echo $?
0
5.组合应用:
[root@localhost ~]# [ $USER == "root" ] &&[ $pwd == "/root" ];echo $?
0
[root@localhost ~]# [ -d "/opt/testdir" ] ||[ -f "/opt/testdir" ] &&echo notfind ||echo a
a
判断及循环:
if单分支语法:
if 条件;then
命令
fi
if多分支语法:
if 条件1;then #条件1成立执行命令1
命令1
elif 条件2;then
命令2
else #条件都不成立执行命令n
命令n
fi
case判断:
case 变量 in #判断变量
模式1) #如果匹配模式1,则执行命令1
命令1;;
模式2) #如果匹配模式2,则执行命令2
命令2;;
*) #都不匹配,执行命令n
命令n;;
esac
for循环:
for i in {seq 10} #数字排序
do
echo $i
done
while循环:
while [ 条件 ]
do
echo aa
done
函数:
在shell环境中,将需要重复的操作定义为公共的语句块
#在脚本中执行定义函数会调用单独的bash
#在命令行定义函数使用的时当前bash进程,并且{之后可以Enter换行
函数定义方法1:
function 函数名 {
命令1
......
}
定义方法2:
函数名(){
命令1
......
}
echo扩展用法:
[root@localhost ~]# echo -e "\033[35mTEST" #30-39m 字体颜色
[root@localhost ~]# echo -e "\033[45mTEST" #40-49m 背景颜色
[root@localhost ~]# echo -e "\033[35mTEST\033[0m" #改变颜色显示后改回来
退出/中断及相关指令:
break 跳出当前所在循环,执行循环体之后的语句块
continue 跳过循环体内余下的语句,进入下一个循环
exit 退出脚本,默认返回值0
用法:
for i in {1..10}
do
[ $i -eq 5 ] &&continue #跳过当前循环
echo $i
done
for i in {1..254}
do
ping -c 1 -i 0.1 -W 1 192.168.4.$i #ping1次,间隔0.1s,1秒返回结果
done
字符串处理:
1.字符串截取:
[root@localhost ~]# a=1234567890
- ${变量名:起始位置:长度} #起始位置从0开始
[root@localhost ~]# echo ${a:5:3}
678
[root@localhost ~]# echo ${#a} #统计变量字符数
10
2.expr工具
[root@localhost ~]# expr substr "$a" 5 3
567
3.cat截取
[root@localhost ~]# echo $a |cut -b 2-6 #-b按字节截取,截取2-6为字符
23456
[root@localhost ~]# echo $a |cut -b 4- #截取第4位到最后
4567890
[root@localhost ~]# echo $a |cut -b 4-5,7-8
4578
2.字符串替换:(基础)a=17628286676
1.替换第一个子串:${变量名/old/new}
[root@localhost ~]# echo ${a/6/x}
17x28286676 #替换第一个
2.替换全部: ${变量名//old/nes}
[root@localhost ~]# echo ${a//6/x}
17x2828xx7x #替换所有
3.字符串删除:A=hand -1 /etc/passwd
[root@localhost ~]# echo ${A#*0:} #删除第一个"0:"之前的全部,包括"0:"
[root@localhost ~]# echo ${A##*0:} #删除最后一个"0:"之前的全部
[root@localhost ~]# echo ${A%:*} #删除右至左第一个":"之后的全部,包括":"
[root@localhost ~]# echo ${A%%:*} #删除右至左最后一个":"之后的全部
4.批量修改文件名:
[root@localhost ~]# for i in `ls /opt/*.doc`
> do
> mv $i ${i%.*}.txt #或mv $i ${i/doc/txt}
> done
5.字符串初值:定义一个变量没有值时的初始值
[root@localhost ~]# xx=11
[root@localhost ~]# echo ${xx:-123}
11
[root@localhost ~]# echo ${yy:-123}
123
6.expext预期交互工具:(配合ssh将交互式软件非交互化)
软件包:expect #which expect #查找命令的绝对路径
#!/bin/bash
expect <<EOF
spawn ssh 192.168.4.5 #创建交互进程
expect "password:" {send "123456\r"}
expect "#" {send "touch /tmp.txt\t"}
expect "#" {send "exit\r"}
EOF
7.数组:
[root@localhost ~]# i=(11 22 33 44 55) #定义数组
[root@localhost ~]# echo ${i[0]} #第一个值为11
[root@localhost ~]# echo ${i[4]} #第五个值为55
[root@localhost ~]# i[1]=111 #为i数组第二个定义值
[root@localhost ~]# echo ${i[1]} #值为111
8.正则表达式:grep工具
grep -q #等同于&>/dev/null
grep -i #不区分大小写
正则符号 | 描述 | 用法 |
---|---|---|
^ | 匹配行首 | grep ^root /etc/passwd |
$ | 匹配行尾 | grep nologin$ /etc/passwd |
[ ] | 匹配集合中任意单个字符 | grep [root] /etc/passwd |
[^ ] | 对集合取反 | grep [^root] /etc/passwd |
. | 匹配任意单个字符 | grep r…t /etc/passwd |
*(不单独使用) | 匹配前一个字符任意次(0-n次) | grep 0* /etc/passwd |
{n,m} | 匹配前一个字符n-m次 | grep a{1,3} /etc/passwd |
{n} | 匹配前一个字符n次 | grep o{3} /etc/passwd |
{n,} | 匹配钱一个字符n次及以上 | grep o{2} /etc/passwd |
() | 保留 |
9.扩展正则:egrep工具或grep -E
正则符号 | 描述 | 用法 |
---|---|---|
+ | 匹配前一个字符1次及以上 | egrep ‘o+’ /etc/passwd |
? | 匹配前一个字符0-1次 | egrep ‘a?’ /etc/passwd |
{n,m} | 匹配前一个字符n到m次 | egrep ‘o{1,2}’ /etc/passwd |
( ) | 组合为整体,保留 | |
| | 或者 | egrep ‘t|g’ /etc/passwd |
\b或<> | 单词边界 | egrep '\bbash\b ’ /etc/passwd |
shell脚本编程:
sed工具:流式编辑器,对字符进行精确操作
非交互过滤修改文件
逐行处理并显示,增删改查
格式:
1.前置命令 |sed [选项] '编辑指令'
2.sed [选项] '编辑指令' 文件
选项: -n 屏蔽默认输出(只显示过滤的内容)
-i 直接修改文件内容
-r 启用扩展正则(排位在最右)
编辑指令: p 打印 print
d 删除 delete
s 替换 substitute
/ / 正则匹配
sed流式编辑器命令:
p打印:
[root@localhost ~]# sed -n '2,4p' /etc/passwd #打印2-4行
[root@localhost ~]# sed -n '4,+10p' /etc/passwd #4行及5-14行
[root@localhost ~]# sed -n '4p;10p' /etc/passwd #4行和10行
[root@localhost ~]# sed -n '/^adm/p' /etc/passwd #打印adm开头的行
[root@localhost ~]# sed -n '/\/bin\/bash$/p' /etc/passwd #打印以/bin/bash结尾的行,用"\"对"/"转义
[root@localhost ~]# sed -n '2~2p' /etc/passwd #显示偶数行
[root@localhost ~]# sed -n '$=' /etc/passwd #显示总行数
[root@localhost ~]# sed -n '=' /etc/passwd #显示行号
d删除:
[root@localhost ~]# sed '1,3d' /etc/passwd #删除1-3行显示
[root@localhost ~]# sed '/root/!d' /etc/passwd #!取反,显示包含root的行
[root@localhost ~]# sed '$d' /etc/passwd #删除最后一行显示
[root@localhost ~]# sed '/^$/d' /etc/passwd #去掉空行显示
s替换:
[root@localhost ~]# sed 's/root/xxx/' /etc/passwd #将每行第一个root替换为xxx
[root@localhost ~]# sed 's/root/xxx/3' /etc/passwd #将每行第三个root替换为xxx
[root@localhost ~]# sed 's/root/xxx/g' /etc/passwd #将每行所有root替换为xxx
[root@localhost ~]# sed '4s/root/xxx/g' /etc/passwd #将第四行所有root替换为xxx
[root@localhost ~]# sed -n 's/root/xxx/p' /etc/passwd #打印修改部分并屏蔽默认输出
# -n '...p' #只显示修改过的
[root@localhost ~]# sed 's/root//g' /etc/passwd #将所有root替换为空
[root@localhost ~]# sed '4,7s/^/#/' /etc/passwd #4-7行行首加#
[root@localhost ~]# sed 's/^#an/an/' /etc/passwd #将#an开头改为an
[root@localhost ~]# cat nssw.txt
Hello the word
nihao ma beijing
[root@localhost ~]# sed -r 's/^(.)(.*)(.)$/\3\2\1/' nssw.txt #将第一个.(字符)存为\1,复制时需将一行内所有字符考虑到
dello the worH
gihao ma beijinn
使用sed修改系统配置:
anonftp.sh
#!/bin/bash
yum -y install vsftpd
cp /etc/vsftpd/vsftpd.conf{,.bak}
sed -i 's/^#anon/anon/' /etc/vsftpd/vsftpd.conf
chmod 777 /var/ftp/pub
systemctl start vsftpd
systemctl enable vsftpd
[root@localhost ~]# chmod +x anonftp.sh
sed多行文本处理:
编辑指令:
i 在指定文本行之前插入 insert
a 在指定文本行之后插入 append
c 替换指定行 change
[root@localhost ~]# sed '2a xxx' /etc/passwd #在第二行后插入xxx
[root@localhost ~]# sed '1,3c xxx' /etc/passwd #将1-3行替换为xxx
导入导出操作:
r 读取文件
w 保存到文件
[root@localhost ~]# sed '4,7r b.txt' /etc/passwd #在4-7行每行后插入b.txt的内容
[root@localhost ~]# sed '4,7w c.txt' /etc/passwd #将4-7行另存为当前目录下c.txt(可自动创建)
[root@localhost ~]# sed '2r /opt/123' /etc/passwd #在2行后插入/opt/123中的内容
[root@localhost ~]# sed '2w /opt/456' /etc/passwd #将第2行另存到/opt/456中
sed的复制粘贴:
模式空间:
存放当前处理行,将处理结果输出,不符合原样输出
处理完当前行再处理下一行
保持空间:
类似于"剪切板",默认存放一个空行(换行符\n)
基本动作:
H 模式空间-->追加-->保持空间
h 模式空间-->覆盖-->保持空间
G 保持空间-->追加-->模式空间
g 保持空间-->覆盖-->模式空间
[root@localhost ~]# sed '1,3H;$G' reg.txt #1-3行追加到保持空间,在末尾追加
[root@localhost ~]# sed '1h;1d;$G' reg.txt #将1行剪切,在末尾追加
awk工具:
以字段为单位对文本过滤
用法:
1.前置命令 |awk [选项] '[条件]{指令}'
2.awk [选项] '[条件]{指令}' 文件
[root@localhost ~]# awk -F: '{print $1,$7}' /etc/passwd #输出每行的第1和第7个字段,-F 指定分隔符(不指定时为空格)
[root@localhost ~]# awk -F: '{print $0}' /etc/passwd #显示全部
[root@localhost ~]# awk -F: '{print NR}' /etc/passwd #显示行数 row 行
[root@localhost ~]# awk -F: '{print NF}' /etc/passwd #显示每行有多少个字段 field 列
-F[:/] #使用多个分隔符
[root@localhost ~]# df -h |awk '/centos/{print "总容量""\t"$2}' #print输出用""标识常量
条件//中不能放置变量,插入变量使用{if($1="")$6=$6+1}
awk处理时机:
awk [选项] '[条件]{指令}' 文件 #{}中不同指令用";"隔开
awk [选项] 'BEGIN{指令}{指令}END{指令}' 文件
awk 'BEGIN{x=0}/bash$/{x++}END{print x}' /etc/passwd #先设x=0,匹配以bash结尾的行执行x++,输出x的值
awk处理条件设置:
1.正则条件:
[root@localhost ~]# awk -F: '/^(root|adm)/{print $1,$3}' /etc/passwd #输出以root或adm开头的用户名和UID
[root@localhost ~]# awk -F: '$1~/root/' /etc/passwd #第一列包含root字样的行(模糊匹配),!~:不要模糊匹配的选项
2.数值/字符串比较条件设置:
等于 == 大于 > 小于 <
不等于 != 大于等于 >= 小于等于 <=
[root@localhost ~]# awk -F: 'NR==3{print}' /etc/passwd #输出第三排
[root@localhost ~]# awk -F: '$3>=1000{print $1,$3}' /etc/passwd #输出UID>=1000的$1和$3
[root@localhost ~]# awk -F: '$3<10{print $1,$3}' /etc/passwd #输出UID<10的$1和$3
3.逻辑条件测试: &&和||
[root@localhost ~]# awk -F: '$3>10&&$3<20{print $1,$7}' /etc/passwd #输出UID>10且UID<20的$1和$7
[root@localhost ~]# awk -F: '$3<10||$3>1000{print $1,$7}' /etc/passwd #输出UID<10或UID>1000的$1和$7
4.运算:
[root@localhost ~]# awk 'BEGIN{x=8;x++;print x+=2}' #11
[root@localhost ~]# awk 'BEGIN{print 23%8}' #7
[root@localhost ~]# seq 200 |awk '$1%3==0' #200以内3个倍数
awk流程控制:
if: 单分支: if(条件){编辑指令}
双分支: if(条件){指令1}else if(条件){指令2}...else{指令n}
[root@localhost ~]# awk -F: '{if($3<=1000){i++}else{j++}}END{print i,j}' /etc/passwd
for:
[root@localhost ~]# awk -F: 'BEGIN{a[0]=0;a[1]=11;a[2]=22;for(i in a){print i,a[i]}}' #将a下标值放入i进行循环
0 0
1 11
2 22