DHCP——Dynamic Host Configuration Protocol
动态主机配置协议
一般适用于客户端的IP分配
1.NetworkManager服务关掉
[root@www ~]# systemctl stop NetWorkManager
[root@www ~]# systemctl disable NetWorkManager
2.在修改dhcp配置文件
[root@www ~]# vi /etc/dhcp/dhcpd.conf // 进入dhcp配置服务
# DHCP Server Configuration file.
# see /usr/share/doc/dhcp*/dhcpd.conf.example
# see dhcpd.conf(5) man page
:r /usr/share/doc/dhcp*/dhcpd.conf.example //r 引入示例文档进行修改
(// set nu 产生行编号
//37,$ s/^/#/ 从37行到末尾添加注释
s 搜索并替换
^ 开头
# 替换符号)
编辑配置文件内容
option definitions common to all supported networks...
option domain-name "www.wayne.com"; // 更改域名
option domain-name-servers 8.8.8.8; // 更改dns
default-lease-time 600;
max-lease-time 7200; // 保留租约时间
将没注释掉的注释掉
subnet 172.16.0.0 netmask 255.255.0.0 { // 设置网号子掩码
range dynamic-bootp 172.16.14.10 172.16.14.20; // 设备dhcp分配范围
option routers 192.168.0.254; // 设置网关
}
3.开启DHCP服务
[root@www ~]# systemctl start dhcpd 开启dhcp服务
[root@www ~]# systemctl enable dhcpd 设备开机自动启动服务
实现自动化运维
bbs.linuxtone.org
bbs.chinaunix.org
if # 如果
case # 案例
for #对于
while # 当....
until # 到...为止
break # 结束并退出循环
continue # 继续下一循环, 在循环中不执行continue下面的代码,转而进入下一轮循环
exit # 退出脚本
shift # ?
array #
function #
shell命令 cp ls date
Linux支持的shell*
[root@www ~]# cat /etc/shells # 查看当前系统中所有的shell类型
[root@www ~]# chsh -l # 查看当前系统中所有的shell类型
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
* 匹配任意多个字符 ls in* rm -rf * rm -rf *.pdf find / -iname "*-eth0"
? 匹配任意一个字符 touch love loove live l7ve; ll l?ve
[] 匹配括号中任意一个字符 [abc] [a-z] [0-9] [a-zA-Z0-9] [^a-zA-Z0-9] ll l[io]ve ll l[^a-z]ve
注意:英文字符顺序: aAbBcCdDeEfFgG...
() 在子shell中执行(cd /boot;ls) (umask 077; touch file1000)
{} 集合 touch file{1..9}
shell 变量? 用一个特定的字符串去表示不固定的内容
1. 自定义变量 var=2019
定义变量: 变量名=变量值 变量名必须以字母或下划线开头,区分大小写 ip1=192.168.2.115
引用变量: $变量名 或 ${变量名} $var
查看变量: echo $变量名 set(所有变量:包括自定义变量和环境变量) echo $var
取消变量: unset 变量名 unset var
作用范围: 仅在当前shell中有效
2. 环境变量
定义环境变量: 方法一 export back_dir2=/home/backup
方法二 export back_dir1 将自定义变量转换成环境变量
引用环境变量: $变量名 或 ${变量名}
查看环境变量: echo $变量名 env 例如env |grep back_dir2
取消环境变量: unset 变量名
变量作用范围: 在当前shell和子shell有效
[root@wayne test]# vi useradd.sh
#!/bin/bash
read -p '请输入要添加的用户名:' name # -p表示提示语句,语句用单引号标识,后边变量前有空格
useradd $name
~
[root@wayne test]# echo $? # 检查脚本是否执行成功,返回0表示成功,其它任意数字没成功
0
数字练习:
第一个版本:
[root@www /test]# vi .nu.sh
#!/bin/bash
read -p "请输入一个数值: " num
if [[ ! "$num" =~ ^[0-9]+$ ]];then # =~表示匹配,正则表达式
echo "你输入的$num不是数字,程序退出!!!"
exit
fi
echo "$num是数字"
[root@www /test]# ./.nu.sh # 测试
请输入一个数值: 22
22是数字
[root@www /test]# ./.nu.sh
请输入一个数值: gg
你输入的gg不是数字,程序退出!!!
[root@www /test]#
数字练习:
第二个版本:(加入循环和判断)
[root@www /test]# vi .nu.sh
#!/bin/bash
#判断用户输入的是否是数字
read -p "请输入一个数值: " num
while : # while 和:之间有空格,否则do行就错误
do
if [[ $num =~ ^[0-9]+$ ]];then # 判断语句 if 后边跟着空格,=~表示匹配,正则表达式
break
else
read -p "不是数字,请重新输入数值: " num # 最后这个变量需要有,因为如果进入到else选项不添加就不会获得新的变量
fi
done
echo "你输入的数字是: $num"
循环要求:循环体,循环终止条件
for循环: for in 后边是确定循环条件,循环次数是固定的(如乘法表)
while循环: while后跟终止条件,循环变量更新,退出条件。条件为假退出,循环次数一般是不固定的,不符合给与条件才退出
until循环: 形式同while相似。但是until条件为真退出,循环次数一般是不固定的,当符合给与条件才退出
Linux 格式:
for ... in ... \\变量名 [ in 取值列表 ]
do
\\循环体
done
C语言 格式:
for ((初值;条件;步长))
do
循环体
done
简单示例:
[root@www ~]# vi for.sh
#!/bin/bash
for i in 1 2 3 4 5 haha hehe nishuia woshita b
do
echo $i
done
[root@www ~]# ./for.sh # 测试
1
2
3
4
5
haha
hehe
nishuia
woshita
b
输出数字,再输出命令
[root@shell script]# vim for2.sh
#!/bin/bash
#for i in `seq 10`
for i in {1..10}
do
echo $i
done #输出数字1到10
#
for i in `ls /` # 执行命令用右引号
do
echo $i
done # 输出目录
进阶示例:
加入双重for循环:
ping练习172.16.0.0网段,查看哪个ip正在使用
[root@www test]# vi i.sh
#!/bin/bash
> /tmp/t.txt # 创建一个文件t.txt
for i in {0..255} # 设置第三个ip块范围
do
echo $i
for ip in {1..254} # 设置末尾ip范围
do
echo 172.16.$i.$ip # 输出 ip
(if ping -c2 172.16.$i.$ip >/dev/null # ping两次ip 将结果输出到null
then
echo 172.16.$i.$ip >>/tmp/t.txt #将输出结果追加写入到t.txt
fi) & # ()表示将内容在子shell里运行,& 转入到后台
done
done # 测试时,可以看到检查的进度,可以通过tail -0f /tmp/t.txt查看正在使用的ip都有哪些,
制作99乘法表
[root@www test]# vi 99.sh
#!/bin/bash
for i in `seq 9` # 取第一个数,取数值1到9(同时表示9次)
do
for j in `seq $i` # 取第二个数,因为i的值是取数值1到9(同时表示9次)
do
echo -e -n "$i*$j=$[$i*$j]\t" # 计算公式说明:$i*$j表示两个数相乘,$[$i*$j]表示乘积结果。-e 使 \t(表示tab对齐的作用) 转义字符生效。-n表示不换行
done
echo
done
[root@www ~]# ./99.sh # 测试
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
变量初始值 条件变量
------------------------------当条件测试成立(条件测试为真),执行循环体
while 条件表达式或者命令(read)
do
循环体
变量的更新 //一定要有变量的更新,否则死循环
done
简单示例
[root@www ~]# vi for.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo $i
let i++
done
[root@www ~]# ./for.sh # 测试结果
1
2
3
4
5
进阶示例
while与输入重定向结合使用
添加用户的脚本,要求用户的信息来自于文本文件
1)创建用户列表文件
[root@shell script]# vim userlist
tom:passtom:2015
jack:passjack:2016
mary:passmary:2022
kite:passkite:2000
2)写添加用户的脚本
[root@shell script]# vi while2.sh
#!/bin/bash
while read line
do
username=`echo $line | cut -d: -f1`
password=`echo $line | cut -d: -f2`
uid=`echo $line | cut -d: -f3`
if id $username &>/dev/null
then
echo "user $username exists."
else
useradd -u $uid $username && echo $password | passwd --stdin $username # && 前边执行成功,执行后边命令
fi
done < /script/userlist
[root@shell script]# sh while2.sh
Changing password for user tom.
passwd: all authentication tokens updated successfully.
Changing password for user jack.
passwd: all authentication tokens updated successfully.
Changing password for user mary.
passwd: all authentication tokens updated successfully.
Changing password for user kite.
passwd: all authentication tokens updated successfully.
变量的初始值
until 条件表达式或者命令
do
循环体
变量的更新
done
说明:当条件为真,退出循环
until与while是相反的
**示例一:**
[root@www test]# cat while.sh
#!/bin/bash
i=0
while [ $i -lt 10 ]
do
echo $i
let i++
done
[root@www ~]# ./for.sh
0
1
2
3
4
5
6
7
8
9
**示例二:**
[root@www test]# cat until.sh
#!/bin/bash
i=0
until [ $i -gt 10 ] # 当条件为大于10 程序停止
do
echo $i
let i++ # 当i=10不大于10只等于10,输出10,到+1的时候发现大于10,循环停止
done
[root@www ~]# ./for.sh
0
1
2
3
4
5
6
7
8
9
10 # ***当gt计算的时候,$i++
----------------------------------下标不再是数值,而是字符
定义关联数组:
申明关联数组变量
普通数组:只能使用整数作为数组索引
关联数组:可以使用字符串作为数组索引
[root@www test]# vi ass.sh
#!/bin/bash
declare -A ass
ass[a]=123
ass[b]=456
ass[c]=789
ass[x]=999
for name in `echo ${ass[*]}`
do
echo $name
done
for i in `echo ${!ass[@]}`
do
echo $i
done
[root@www ~]# cat shellarr.sh
#!/bin/bashdeclare -A sharr //定义一个数组
cut -d: -f7 /etc/passwd > /tmp/shell.txt //截取passwd里shell列
while read name // 读 一行
do
let sharr[$name]++ //再读一行 建立一个变量方便下边循环取值
done < /tmp/shell.txt //写入/tmp/shell.txt
for ind in `echo ${!sharr[@]}` // 将sharr里的内容进行遍历 (拿出来看)
do
echo "$ind : ${sharr[$ind]}" // $ind 下标 ,${sharr[$ind]} 数值
done
[root@www test]# sh c.sh # 输出结果解释:路径为下标值,数值为显示的次数
/sbin/nologin : 36
/bin/sync : 1
/bin/bash : 7
/sbin/shutdown : 1
/sbin/halt : 1
用一组特殊的字符,表示匹配的内容。
用来处理文本文件(可编辑的)。
普通字符:大小写字母 数字
元字符:特殊含义的字符
使用普通字符举例:
[root@shell /shell]# grep "root" passwd # 查找包含root的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
使用普通字符
[root@shell /shell]# grep "^root" passwd # 查找以root开头的行
root:x:0:0:root:/root:/bin/bash
[root@shell /shell]# grep "bash$" passwd # 查找包含bash末尾的行
root:x:0:0:root:/root:/bin/bash
s:x:1000:1000:s:/home/s:/bin/bash
匹配空行 (linux中文本文件每行结尾$表示,空行也一样)
[root@shell /shell]# cat -A p1
[root@shell /shell]# grep "^$" p1
[root@www test]# cat f1
rot
root
roooot
rooooooooooot
rt
at
[root@www test]# grep 'r..t' f1 # rt之间包含2个字符
root
[root@www test]# grep 'r.t' f1 # rt之间包含一个字符的
rot
[root@www test]# grep '.t' f1
rot
root
roooot
rooooooooooot
rt
at
[root@www test]# grep '^.t' f1 # 以^开头,设置个限制,t是末尾,.中间一个字符。
rt
at
[root@shell /shell]# grep "r*t" f1 # *对r来说可以是0~无限字符,r可以没有,所以包含at
rot
root
roooot
rooooooooot
rt
at
[root@shell /shell]# grep "ro*t" f1 # *对o来说取值,r在开头取范围,所以没有at
rot
root
roooot
rooooooooot
rt
[ ] 匹配指定字符组中的任意1个字符
[A-Z]
[a-z]
[a-Z] 所有的字母
[0-9]
[a-Z0-9] 字母+数字
[^a-Z0-9] ^取反,不是字母+数字 == 符号
装 13 表示法,POSIX表示法:
man grep 向下找
[[:alnum:]] == [a-Z0-9] 包含大小写字母,数字
[[:alpha:]] == [a-Z] 包含大小写字母
[[:lower:]] == [a-z] 包含小写字母
[[:upper:]] == [A-Z] 只包含大写字母
[[:digit:]] == [0-9] 十进制数 数字
[[:punct:]] == 符号 符号
[[:space:]] == 空白字符(tab 空格)
passwd文件,输出用户名是4个字母的行?
[a-Z][a-Z][a-Z][a-Z]
[root@shell test]# grep "^[a-Z][a-Z][a-Z][a-Z]" passwd # ^ 开始 用[a-Z]分别表示四个字符
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
f2文件,输出有3个连续一样的字符的行?
[root@shell /shell]# cat f2 # 添加一个这样的文件
abc
123
qwe
AAA
zxc
BBB
###
@#$
[root@shell /shell]# grep "\(.\)\1\1" f2 # (.)包含任意一个,\1\1 表示三个字符 grep "^\(.\)\1\1$" f2 严谨设置取值范围
AAA
BBB
###
7. \{ \} 表示要取值得范围
\{m\} 前面的字符有m个
\{m,\} 前面的字符>=m个
\{m,n\} 前面的字符>=m <=n 个,
[root@shell test]# grep "^[a-Z]\{4\}:" passwd # 前边取四个值
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
[root@shell test]# grep "^[a-Z]\{4,\}:" passwd # 前边取值大于等于四个值
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@shell test]# grep "^[a-Z]\{4,8\}:" passwd # 前边取值大于等于四个值,小于8个值
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
[root@shell test]# grep "^\<[a-Z]\{4,8\}\>" passwd # 这样就界定取值是什么位置的单词词组
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@shell /shell]# cat f3
r.t
r*t
rat
rot
r$t
[root@shell /shell]# grep "r.t" f3 # 按照 . 作用,只能找到替代一个字符的
r.t
r*t
rat
rot
r$t
[root@shell /shell]# grep "r\.t" f3 # 在符号前边添加转义字符可以显示出符号,否则会显示元字符的特殊作用
r.t
‘’ 强引用符号
" " 弱引用符号
` $ \ 不能屏蔽
[root@shell /shell]# grep "t$" f3 # 双引号无法屏蔽 $字符
r.t
r*t
rat
rot
r$t
[root@shell /shell]# grep 't$' f3 # 单引号无法屏蔽 $字符
r.t
r*t
rat
rot
r$t
在正则表达式中,没有影响。
[root@shell /shell]# touch "\" # \ 表示转义,所以无法创建
> ^C
[root@shell /shell]# touch '\\' # 使用转义字符屏蔽掉元字符的特殊含义
[root@shell /shell]# ls
\
在shell中,有效果。
扩展正则元字符
| 或
+ 前面的字符匹配>=1次(1~无穷大)
? 前面的字符配置0次或1次
() == ()
{m} == {m}
{m,} == {m,}
{m,n} == {m,n}
egrep 用在扩展正则
| 或
[root@shell /shell]# cat f4 # 添加文件
a
bb
ccc
abc
cde
[root@shell /shell]# egrep "a|bb" f4 # | 将两个匹配条件符合的都输出
a
bb
abc
[root@shell /shell]# egrep "aa|bb" f4 # | 搜索前边或后边,前边无匹配无输出,后边匹配输出后边
bb
+ 前面的字符匹配>=1次(1~无穷大)
[root@shell /shell]# egrep "r+t" f1 # 表示t前边至少有一个r
rt #符合
[root@shell /shell]# egrep "ro+t" f1 # 表示o至少一个或者无限个
rot # 有一个,其它是多个o
root
roooot
rooooooooot
? 前面的字符配置0次或1次
[root@shell /shell]# egrep "r?t" f1 # ?对r负责,r可以没有,或者无限
rot
root
roooot
rooooooooot
rt # 前边有r 其余没有r,t前边是o
at
[root@shell /shell]# egrep "ro?t" f1 # ?对前边o负责
rot # 有一个o
rt # 没有o
( ) == \( \) 在egrep里 作用相同
[root@shell /shell]# egrep "(.)\1\1" f2 # 在正则里括号可以不用 \
AAA
BBB
###
fgrep
取消元字符的特殊含义。
[root@shell /shell]# fgrep "r.t" f3 # 屏蔽一切元字符的含义,搜啥找啥(傻瓜式搜索)
r.t
[root@shell /shell]# fgrep "r*t" f3
r*t
sed + 正则表达式
处理文本文件的流编辑器,可以过滤和转换。
将文本文件,以行 为单位,“流”入模式空间,使用命令、选项进行处理,处理完,打印到标准输出。(sed命令:如果不加 -i 只改变输出,不改变原文件)
然后再处理下一行,直到结束。
与grep对比:
grep只有匹配,没有修改
与vi对比:
光标在哪,就编辑哪;
sed是默认处理文件所有的行。
选项:
-n * 关闭模式空间的输出
-e * 多点编辑
-i ***
-f
-r *
命令:
d *** 删除匹配行
p *** 打印匹配行
q *** 退出
s ***** 替换(重点)
y ***
r
w
a
i
c
h H
g G
语法:
sed [选项] ‘/定址/命令’ 文件名
定址:通知sed,处理文件的哪一行;如果不写,处理所有的行。
例子: vi一个带序列的文件进行如下操作
介绍定址,使用命令 d 或 p。
[root@shell /shell]# sed 'd' p3
没有加定址,所有行被删掉
[root@shell /shell]# sed '1d' p3
[root@shell /shell]# sed '5d' p3
定址使用行号,删除第1行,第5行
[root@shell /shell]# sed '1,3d' p3
使用2个定址,删除区间 1-3行
[root@shell /shell]# sed '1~2d' p3 # 删除奇数行,从1行开始删除
[root@shell /shell]# sed '2~2d' p3 # 删除偶数行,从2行开始删除
删除第1行和第5行
[root@shell /shell]# sed '1d;5d' p3
||
[root@shell /shell]# sed -e '1d' -e '5d' p3 # -e 可以同时支持多个指令,操作更灵活
使用定址删除:
[root@shell /shell]# sed '/1001/d' p3 # 删除指定行
[root@shell /shell]# sed '/1001/,/1005/d' p3 # 删除从包含1001行 到 1005行,包括之间行都删除
定址使用正则表达式
关于定制删除需要了解:
[root@shell /shell]# sed '/1010/,/1005/d' p3
前面的定址在文件中没有,操作不执行
[root@shell /shell]# sed '/1005/,/1010/d' p3
后面的定址在文件中没有,从第一定址直接匹配到文件结束,执行操作
p 打印匹配行
[root@shell /shell]# sed 'p' p3 # 不指定,默认打印全部行
[root@shell /shell]# sed '1p' p3 # 打印第一行
[root@shell /shell]# sed '1,3p' p3 # 打印从第一行到第三行
[root@shell /shell]# sed -n '1,3p' p3 # 关闭空间模式打印一行
打印奇数行
打印偶数行
[root@shell /shell]# sed -n '1~2p' p3 # 打印奇数行
[root@shell /shell]# sed -n '2~2p' p3 # 打印偶数行
打印3的倍数行
[root@shell /shell]# sed -n '0~3p' p3 # 打印3的倍数行
打印第1行和第5行
[root@shell /shell]# sed -n '1p;5p' p3 # 打印第1行和第5行
||
[root@shell /shell]# sed -n -e '1p' -e '5p' p3 # 打印第1行和第5行
q 退出
[root@shell /shell]# sed '1q' p3 # 遍历一条就退出
[root@shell /shell]# sed '3q' p3 # 遍历
打印文件的第一行:
模拟 head -1
[root@shell /shell]# sed -n '1p' p3
[root@shell /shell]# sed '1!d' p3
[root@shell /shell]# sed '1q' p3 这条最好
最后一条最好,因为只遍历一条就退出;另外两条是对全文件进行遍历
s 查找替换
语法结构:s/模式匹配/替换内容/旗标
模式匹配 正则表达式
替换内容 将模式匹配的内容替换成什么内容
旗标:
n:1-512之间的正整数,表示第n次出现的匹配内容
g:全局替换
p:打印替换的行
w:另存为
[root@shell /shell]# sed 's/user/USER/' p3 # 将小写替换成大写(不添加表示默认每行第一个)
[root@shell /shell]# sed 's/user/USER/2' p3 # 将小写替换成大写(表示每行第二个)
[root@shell /shell]# sed 's/user/USER/g' p3 # 将小写替换成大写(g表示全部替换)
[root@shell /shell]# sed -n 's/root/ROOT/p' p1 # -n关闭空间模式,p打印小写替换大写的行
ROOT:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/ROOT:/sbin/nologin
[root@shell /shell]# sed -n 's/root/ROOT/gp' p1 # 参数里的gp可以不区分顺序
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
operator:x:11:0:operator:/ROOT:/sbin/nologin
[root@shell /shell]# sed -n 's/root/ROOT/pg' p1
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
operator:x:11:0:operator:/ROOT:/sbin/nologin
[root@shell /shell]# sed -n 's/root/ROOT/2p' p1 # 参数里的2p可以不区分顺序
root:x:0:0:ROOT:/root:/bin/bash
[root@shell /shell]# sed -n 's/root/ROOT/p2' p1
root:x:0:0:ROOT:/root:/bin/bash
[root@shell /shell]# sed 's/root/ROOT/w file1' p1 # w 另存,默认当前路径保存,也可以指定路径
[root@shell /shell]# cat file1
ROOT:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/ROOT:/sbin/nologin
[root@shell /shell]# sed 's/root/ROOT/w /tmp/file1' p1 # w 另存,可以指定路径
y 根据指定位置替换(这种模式下字母必须一一对应)
[root@shell /shell]# sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' p3
# 将一个文件中,所有的小写字母,替换成大写字母(这种模式下字母必须一一对应)
a 在匹配行下面插入内容
i 在匹配行上面插入内容
c 本行替换
a 在匹配行下面插入内容 (a前边不指定行数,默认每一行)
[root@shell /shell]# sed 'a hehe' p3 # 在文件p3每一行下插入hehe
[root@shell /shell]# sed '
hehhe' p3 # 在文件p3第一行下插入hehe
i 在匹配行上面插入内容
[root@shell /shell]# sed 'i hehhe' p3 # 在文件p3每一行上插入hehe
[root@shell /shell]# sed '1i hehhe' p3 # 在文件p3第一行上插入hehe
c 本行替换
[root@shell /shell]# sed 'c hehhe' p3 # 在文件p3每一行上替换hehe
[root@shell /shell]# sed '1c hehhe' p3 # 在文件p3第一行上替换hehe
r 读取一个文件的内容
[root@www test]# sed 'r f1' passwd # 将文件f1里的内容插入到passwd文件的每一行下
w 另存为
[root@www test]# sed 'w pass.txt' passwd # 将文件passwd另存一份 pass.txt
r 读取一个文件的内容(不改变原文件,空间模式显示)
[root@shell /shell]# sed 'r apache.txt' p3 写入引号的文件内容到引号外的文件里,不指定行就是在每一行写入
[root@shell /shell]# sed '3r apache.txt' p3 将引号里的文件引入到引号外的文件第三行开始写入
w 另存为
[root@shell /shell]# sed -n '1w p31' p3 引入p3第一行,另存一个文件p31里,-n关闭空间模式
[root@shell /shell]# cat p31
user1:x:1000:1000::/home/user1:/bin/bash
g 将保留空间的内容,复制到模式空间,覆盖原来模式空间的内容
G 将保留空间的内容,追加到模式空间,保留原来模式空间的内容
h 将模式空间的内容,复制到保留空间,覆盖原来保留空间的内容
H 将模式空间的内容,追加到保留空间,保留原来保留空间的内容
H 在前边 ;分号隔离,g
sed
处理文本文件–模式空间(PATT)
可以用来存储文件内容(行)–保留空间(HOLD),保留空间,默认有一个空行
从老师那里下载了一个调试脚本,查看工作模式状态
“lftp 172.16.0.99
下载调试文件 sedsed-1.0
chmod +x sedsed-1.0
mv sedsed-1.0 sedsed
mv sedsed /bin/
cd /shell/”
sedsed -d ‘1h;3g’ p3 # sedsed -d是调试脚本的选项
sed ‘1h;3g’ p3
sed ‘1h;3G’ p3
sed ‘1H;3g’ p3
sed ‘1H;3G’ p3
[root@www test]# sed '1h;4g' f1 # 1h将第一行,复制到保留空间,然后g从保留空间取回覆盖第4行
rot
root
roooot
rot
rt
at
[root@www test]# sed '1h;4G' f1 # 1h将第一行,复制到保留空间,然后G从保留空间取回追加第4行 尾
rot
root
roooot
roooooooot
rot
rt
at
[root@www test]# sed '1H;4g' f1 # 1H将第一行,复制到保留空间(上边有空格),然后G从保留空间取回覆盖第4行 尾(带着空格)
rot
root
roooot
rot
rt
at
[root@www test]# sed '1H;4G' f1 # 1H将第一行,复制到保留空间(上边有空格),然后G从保留空间取回追加第4行 尾(带着空格)
rot
root
roooot
roooooooot
rot
rt
at
awk是一个优良的文本处理工具。
工作模式:
行处理模式
在处理文件时:
读入文件的行,将行存入内置变量 $0 中
再使用内置变量 FS(列的分隔符,默认是空白字符(空格或tab)) 将行拆分成若干列
第1列 存入 内置变量$1
第2列 存入 内置变量$2
…
开始处理
输出的时候,再使用内置变量OFS(输出列的分隔符,默认是空格)
继续处理下一行
[root@shell /shell]# awk -F: '{print $0}' p3 输出行
[root@shell /shell]# awk -F: '{print $1}' p3 # 输出第一列
[root@shell /shell]# awk -F: '{print $1,$3}' p3 # 输出第一列,和第三列
语法:
awk [选项] ‘/定址/{动作}’ 文件名
选项:
-F 指定列的分隔符
-f 调用脚本
动作:
print 标准输出
printf 格式化输出
定址:
正则表达式
模式计算
…
awk的分隔符:
默认的:空格或tab
[root@centos7-bj /var/log/httpd]# awk ‘{print $1}’ access_log # 不添加-F分隔符表示默认分隔符为 空格或者tab
tab
实现windows下的excel和centos进行文件交互。
在linux下通过awk输出格式后,复制到excel可以直接按列粘贴,方便!
[root@shell /shell]# awk -F: '{print $1"\t"$3}' p3
user1 1000
user2 1001
user3 1002
user4 1003
user5 1004
user6 1005
user7 1006
user8 1007
user9 1008
user10 1009
\t 表示 tab键
[root@shell /shell]# awk -F [:/] '{print $10,$11}' p3
指定2个符号,做分隔符 ,[ ]里是“或”的关系
[root@shell /shell]# awk -F "" '{print $1}' p3
指定 空 ,做分隔符
输出:
print 普通输出
printf 格式化输出
%s 字符串:包含所有的字母 数字 符号
%d 十进制整数:小数直接取整,字母 符号归0
%f 浮点数:默认,小数点后面保留6位,不够添0,;字母 符号 归0
输出,行尾默认是没有换行符 ,换行时末尾添加 \n
%的数量 <= $ (%小于¥变量的数量才有输出结果,参考下边例子)
创建一个演示文件
[root@shell /shell]# cat a1
23.456 11.234 66 aa bcd #@
%s 可以输出显示所有字符
[root@shell /shell]# awk '{printf "%s,%s;%s-%s_%s\t%s\n",$1,$2,$3,$4,$5,$6}' a1
# %s 可以输出显示所有字符
23.456,11.234;66-aa_bcd #@
%d 可以输出整数,不是整数的识别成0
[root@shell /shell]# awk '{printf "%d,%d;%d-%d_%d\t%d\n",$1,$2,$3,$4,$5,$6}' a1
# %d 可以输出整数,不是整数的识别成0
23,11;66-0_0 0
%f 可以输出识别输出所有小数,并且默认保留小数后六位
[root@shell /shell]# awk '{printf "%f,%f;%f-%f_%f\t%f\n",$1,$2,$3,$4,$5,$6}' a1
# %f 可以输出识别输出所有小数,并且默认保留小数后六位
23.567000,11.234000;66.000000-0.000000_0.000000 0.000000
对齐演示:
[root@shell /shell]# awk -F: '{printf "%s %d\n",$1,$3}' passwd
常规输出
root 0 15表示$1列最长的是15个字符,5表示$3列最长的是5个字符
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14
nobody 99
[root@shell /shell]# awk -F: '{printf "%15s %5d\n",$1,$3}' passwd
右对齐
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
[root@shell /shell]# awk -F: '{printf "%-15s %-5d\n",$1,$3}' passwd
左对齐
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
画表格:
[root@shell /shell]# awk -F: '{printf "|%-15s|%-5d|\n-----------------------\n",$1,$3}' passwd
画上表格 用 | 分割 ,用___\n上下分割
[root@shell /shell]# awk '{printf "%10.1f %10.2f\n",$1,$2}' a1
23.6 11.23 # 默认向右对齐
[root@shell /shell]# awk '{printf "%-10.1f %-10.2f\n",$1,$2}' a1
23.6 11.23 # 添加 - 向左对齐
10是输出的宽度
.1是小数点后面保留几位,四舍五入
- 左对齐
定址:
[root@shell /shell]# awk -F: '/^root/{print $1}' passwd
root
[root@shell /shell]# awk -F: '$3 ~ /\<[0-9]\>/{print $1,$3}' passwd
> < == != >= <=
3. 逻辑运算符
&& (2个条件都要满足)
|| (2个条件满足一个就行)
! (条件取反)
[root@shell /shell]# awk -F: '$3 == 0{print $1,$3}' passwd
# 筛选第三列 是0的,输出第一列和第三列
[root@shell /shell]# awk -F: '$3 >= 10{print $1,$3}' passwd
# 筛选第三列 大于等于10的,输出第一列和第三列
[root@shell /shell]# awk -F: '$3 != 10{print $1,$3}' passwd
# 筛选第三列 不等于10的,输出第一列和第三列
[root@shell /shell]# awk -F: '$3 >= 1 && $3 <=10{print $1,$3}' passwd
# 筛选第三列 大于等于1的 并且 小于等于10的,输出第一列和第三列
[root@shell /shell]# awk -F: '$3 >=5 || $3 <= 3{print $1,$3}' passwd
# 筛选第三列 大于等于5的 或者 小于等于3的,输出第一列和第三列
[root@shell /shell]# awk -F: '!($3 >= 1 && $3 <=10){print $1,$3}' passwd
# 筛选第三列 不要(大于等于5的 并且 小于等于3)的,输出第一列和第三列,当条件相反时,条件用括号标注
关系运算比较,要求是数值型数据;
~ !~ 可以是数值型,也可以是字符型 (~匹配;!~ 不匹配)
[root@shell /shell]# awk -F: '$3 ~ /1/{print $1,$3}' passwd
# $3匹配1的
[root@shell /shell]# awk -F: '$3 !~ /1/{print $1,$3}' passwd
# 筛选$3这列,不匹配1的
4. 算数运算符
+ - * / % ^(幂运算)
[root@shell /shell]# cat num
2 9 4
7 5 3
6 1 8
[root@shell /shell]# awk '$3-$2 >=1{print $3,$2}' num
# 计算$3减去$2结果大于等于1的,按照$3,$2 顺序显示出来
8 1
[root@shell /shell]# cat f6
zhangyi 80 85 86
lier 78 76 90
wangsan 91 89 75
求出每个人的总成绩?平均分?
[root@shell /shell]# awk '{print $1,$2+$3+$4,($2+$3+$4)/3}' f6
zhangyi 251 83.6667
lier 244 81.3333
wangsan 255 85
格式化输出,名字 总成绩,平均分保留2位小数
[root@shell /shell]# awk '{printf "%-7s %-3d %-5.2f \n",$1,$2+$3+$4,($2+$3+$4)/3}' f6
awk的完成格式:
BEGIN{} 在处理文本文件之前,执行的操作
打出表头
设置变量
定义分隔符
只执行1次
/定址/{} 处理文本文件,有定址,处理匹配定址的行;没有定址,处理整个文件
文件有几行,执行几次
END{} 在处理文本文件之后,执行的操作
数据汇总
只执行1次
[root@shell /shell]# awk 'BEGIN{print "|姓名|总成绩|平均分|";print "-------------------"}{printf "|%-7s|%-3d|%-5.2f|\n-------------------\n",$1,$2+$3+$4,($2+$3+$4)/3}' f6
|姓名|总成绩|平均分| # BEGIN{print “”} 可以添加标题,
-------------------
|zhangyi|251|83.67|
-------------------
|lier |244|81.33|
-------------------
|wangsan|255|85.00|
-------------------
1. 内置变量
$0
$1 $2 $3 …
FS 输入列的分隔符
OFS 输出列的分隔符
(1)NR 行号
[root@shell /shell]# awk ‘{print NR,$0}’ p3 # NR添加行号。($0表示每一行)
[root@shell /shell]# awk ‘NR1{print $0}’ p3 ## 打印第一行,NR在{ }前边表示第几行
[root@shell /shell]# awk 'NR1 || NR==3{print $0}’ p3 ## 打印第一行和第三行,NR在{ }前边表示第几行
[root@shell /shell]# awk ‘NR>=1 && NR<=3{print $0}’ p3 ## 打印第一行到第三行 (范围行数)
(2)NF 列的数量
文件中,列的数量不一致。(比如个人信息,每个人填的不一样多)
[root@shell /shell]# awk ‘{print $NF}’ a1 # 取每一行的最后一列(最后一个)
倒数第1列
[root@shell /shell]# awk ‘{print $(NF-1)}’ a1 # 倒数第二列 NF-1
倒数第2列
(3)FS 一般在脚本里使用
== -F
[root@shell /shell]# awk 'BEGIN{FS=":"}{print $1}' p3 #
BEGIN{FS=":"}代替 -F
(4)OFS
[root@shell /shell]# awk 'BEGIN{FS=":";OFS="\t"}{print $1,$2,$3,$4}' p3 # 按照 : 分隔符划分列,然后输出$1,$2,$3,$4,输出后按照tab格式间隔开
自定义变量
变量=值
变量=数
变量=“字符串”
赋值运算:
a=5
a+=5 a=a+5
a-=5
[root@shell /shell]# awk ‘{total=$2+$3+$4;print $1,total,total/3}’ f6
zhangyi 251 83.6667
lier 244 81.3333
wangsan 255 85
[root@shell /shell]# awk ‘{total=$2+$3+$4;avg=total/3;print $1,total,avg}’ f6
zhangyi 251 83.6667 total变量表示总和
lier 244 81.3333 avg 变量表示平均数
wangsan 255 85 输出第一列,总和,平均分
[root@shell /shell]# awk '{a+=1;print a}' p3
1
2
3
4
5
6
7
8
9
10
[root@shell /shell]# awk '{a+=1}END{print a}' p3
10
[root@shell /shell]# cat f6
name ULE ULA oracle
zhangyi 80 85 86
lier 78 76 90
wangsan 91 89 75
打印每科的总成绩?
[root@shell /shell]# awk '{ule+=$2;ula+=$3;oracle+=$4}END{print ule,ula,oracle}' f6
# 打印每科的总成绩
249 250 251
写awk脚本:
把命令行搬到文件里。
[root@shell /shell]# vim f6.awk1
BEGIN{
}
{
ule+=$2
ula+=$3
oracle+=$4
}
END{
print ule,ula,oracle
}
[root@shell /shell]# awk -f f6.awk1 f6
249 250 251
if (判断条件)
{
动作
}
else
{
动作
}
多分支判断
if (判断条件)
{
动作
}
else if (判断条件)
{
动作
}
else if (判断条件)
{
动作
}
else
{
动作
}
[root@shell /shell]# cat f6
name ule ula oracle
zhangyi 80 85 86
lier 78 76 90
wangsan 91 89 75
zhaosi 65 77 57
liuwu 78 67 54
zhouliu 85 79 91
maqi 55 67 63
判断标准:
A 90-100
B 80-89
C 70-79
D 60-69
E 0-59
统计:ule个标准的人数有几个?
BEGIN{
a=0
b=0
c=0
d=0
e=0
#可以这么写:a=b=c=d=e=0
}
NR>1{
if($2>=90 && $2<=100)
{
a+=1
}
if($2>=80 && $2<=89)
{
b+=1
}
if($2>=70 && $2<=79)
{
c+=1
}
if($2>=60 && $2<=69)
{
d+=1
}
if($2>=0 && $2<=59)
{
e+=1
}
}
END{
print "ULE成绩是A的有"a"人"
print "ULE成绩是B的有"b"人"
print "ULE成绩是C的有"c"人"
print "ULE成绩是D的有"d"人"
print "ULE成绩是E的有"e"人"
}
(1)while
变量=初值
while (条件表达式)
{
动作
变量更新
}
(2)for
for(变量=初值;变量的取值范围;变量更新)
{
动作
}
倒序输出passwd文件的每一列:
while方式:
BEGIN{
FS=":" # 表示标记文件文件的分隔符
}
{
i=NF # i=NF 表示列数
while(i>1) # 循环开始:当i大于1的时候
{
printf "%s:",$i 输出列
i=i-1
}
print $1
}
BEGIN{
FS=":"
}
{
for(i=NF;i>1;i--)
{
printf "%s:",$i
}
print $1
}
循环 + 判断
[root@shell /shell]# cat num
2 9 4
7 5 3
6 1 8
练习:
打印出每行最大的数字?
{
max=0
i=1
while (i<=NF)
{
if (max<$i)
{
max=$i
}
i=i+1
}
print max
}
打印出每行最小的数字?
{
min=999999999999
i=1
while (i<=NF)
{
if (min>$i)
{
min=$i
}
i=i+1
}
print min
}
打印出整个文件最大的数字?
BEGIN{
max=0
}
{
i=1
while (i<=NF)
{
if (max<$i)
{
max=$i
}
i=i+1
}
}
END{
print max
}
打印出整个文件最小的数字?
awk的数组
数组用于存储一组值。
数组里面的值(元素)用数组下标来表示。
数组名[下标]=元素
数组名 [a-Z][a-Z0-9_]*
下标 数字(正整数)
元素 "字符串" 数字
name ule ula oracle
zhangyi 80 85 86
lier 78 76 90
wangsan 91 89 75
zhaosi 65 77 57
liuwu 78 67 54
zhouliu 85 79 91
maqi 55 67 63
每个人的总成绩,总平均分
求每科的平均分:每科总成绩/(NR-1)
ule_total+=$2
ule_avg=ule_total/(NR-1)
需求:
每科超过平均分的有几个人?都是谁?
练习:模拟tac
元素 $0
下标
正整数 没有定义,默认从0开始;可以定义从1开始
NR
名字
{
line[i++]=$0
}
END{
for(j=NR-1;j>=0;j--)
{
print line[j]
}
}
下标从0开始,到NR-1结束
BEGIN{
i=1
}
{
line[i++]=$0
}
END{
for(j=NR;j>=1;j--)
{
print line[j]
}
}
下标从1开始,到NR结束
{
line[NR]=$0
}
END{
for(j=NR;j>=1;j--)
{
print line[j]
}
}
下标直接使用NR
完成需求:
BEGIN{
ule_total=0 # 定义各科的初始值为0
ula_total=0
oracle_total=0
ule_num=ula_num=oracle_num=0 # 定义各科的平均分人数为0
}
NR>1{
# 成绩的累加
ule_total+=$2 # 计算各科的总和
ula_total+=$3
oracle_total+=$4
# 数组传值
name[NR]=$1 # 定义名字的数组
ule[NR]=$2 # 定义ule科目的数组
}
END{
# 求出各科的平均分
ule_avg=ule_total/(NR-1) # 计算平均分 (NR-1)表示出了标题行的所有行
ula_avg=ula_total/(NR-1)
oracle_avg=oracle_total/(NR-1)
printf "ULE的平均分是:%.1f\n",ule_avg # 输出结果
printf "ULA的平均分是:%.1f\n",ula_avg
printf "ORACLE的平均分是:%.1f\n",oracle_avg
# 求出超过ule平均分的人数
# 定义一个新的数组,将超过平均分的人名传给数组
for(i=2;i<=NR;i++) # 设置条件(i自定义取值),因为没有标题行,所以i从2开始;(i<=NR)表示NR从2开始大于等于i;(i++)表示i增加
{
if (ule[i]>ule_avg)
{
ule_num+=1
new_name[j++]=name[i] # 定义一个新的数组,将超过平均分的人名传给数组
}
}
print "超过ule平均分的有"ule_num"个人"
# 遍历超过ule平均分的人名数组
printf "超过ule平均分的是:"
for (k=0;k<=ule_num;k++)
{
printf new_name[k]" "
}
printf "\n" # 为了输出结果时,光标不跟随显示,添加换行符
}
求出各科最高分是谁?
BEGIN{
ule_max=ula_max=oracle_max=0
}
if ($2>ule_max)
{
ule_max_name=$1
ule_max=$2
}
awk 常用函数
sub gsub 替换
[root@shell /shell]# cat pet
cat dog bird pig
dog cat dog bird
cat bird cat cat
[root@shell /shell]# awk '{sub(/cat/,"snake");print}' pet
snake dog bird pig
dog snake dog bird
snake bird cat cat
[root@shell /shell]# awk '{gsub(/cat/,"snake");print}' pet
snake dog bird pig
dog snake dog bird
snake bird snake snake
[root@shell /shell]# awk '{gsub(/cat/,"snake",$3);print}' pet
cat dog bird pig
dog cat dog bird
cat bird snake cat
替换第3列的猫为蛇
toupper() 小写转大写
tolower() 大写转小写
[root@shell /shell]# awk ‘{print toupper($0)}’ pet
[root@shell /shell]# awk ‘{print toupper($1)}’ pet
[root@shell /shell]# awk ‘{print toupper($1),toupper($2)}’ pet
文本文件的处理命令:
grep
sed
awk ***
处理文本文件只是让其输出更人性化。
sed -i 更改原文件。
[root@shell /shell]# sed -i 's/cat/CAT/' pet
[root@shell /shell]# cat pet
CAT dog bird pig
dog CAT dog bird
CAT bird cat cat
[root@shell /shell]# sed -i.bak 's/CAT/cat/g' pet
改变的同时,原文件备份下来
[root@shell /shell]# cat pet
cat dog bird pig
dog cat dog bird
cat bird cat cat
[root@shell /shell]# cat pet.bak
CAT dog bird pig
dog CAT dog bird
CAT bird CAT CAT
sed -r 让sed支持扩展正则
了解$*,$@作用
[root@www test]# sh for.sh a b c d e f
print $*:
a b c d e f
1 # $*表示输入的参数是一个整体,共1个参数
print $@:
a
b
c
d
e
f
6 # $*表示输入的参数都是独立的个体,共6个参数
seq的使用方法
seq 10 # 表示从1-10
seq 0 10 # 表示从0-10
seq 1 2 10 # 表示从1-10 步数为2,结果为1,3,5,7,9
seq -w 01 09 # -w 表示等宽显示
seq -w 10 # -w 如果数字1到10 那么按照10宽度显示
seq 5 -1 1 # 5 到1 倒数 步数为1
先取值后计算,先计算后取值
[root@shell script]# vim while1.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo $i
let i++
done
[root@www ~]# ./while.sh
1
2
3
4
5
i++:先赋值,再计算
++i: 先计算,再赋值
let i++
let ++i
i–
–i
由$ 符号延伸到下边内容
由$ 符号延伸到下边内容
unix2dos $ --> ^M$
dos2unix ^M$ --> $
window编辑的脚本会存在^M$
linux通过安装unix2dos 可以转换格式
[root@shell test]# cat -A p2.txt
123^M$
^M$
^M$
abc
执行转换命令
[root@shell test]# dos2unix p2.txt
dos2unix: converting file p2.txt to Unix format ...
[root@shell test]# cat -A p2.txt
123$
$
$
abc
命令 | 常用的选项及作用 |
---|---|
read | -p 后边跟提示语句 |
read | -t 表示延时操作时间(秒) |
read | -n 限制输入的位数 |
[ 1 -eq 10 ] | 等于 |
[ 1 -ne 10 ] | 不等于 |
[ 1 -ge 10 ] | 大于等于 |
[ 1 -gt 10 ] | 大于 |
[ 1 -le 10 ] | 小于等于 |
[ 1 -lt 10 ] | 小于 |
[ -d dir ] | 判断是否为目录 |
[ -f file ] | 判断是否为文件 |
[ -r file ] | 判断对该文件是否有读权限 |
[ -x file ] | 判断对该文件是否有执行权限 |
[ -w file ] | 判断对该文件是否有写权限 |
[ -s file ] | 判断文件是否为空的,不是空文件$?返回0值 |
[ -e file ] | 表示如果filename存在,则为真 |
[ ! -e file ] | ! 表示取非,如果filename存在,则为假 |
( ) | 子shell中执行 |
(( )) | 数值比较,运算 C语言 |
$( ) | 命令替换 |
$(( )) | 整数运算 |
[ ] | 条件测试 |
[[ ]] | 条件测试,支持正则 =~ |
$[ ] | 整数运算 |
{ } | |
${ } | |
continue | 跳出当次循环 |
break | 跳出整个循环 |
[root@slave1 logs]# date
Tue Aug 28 21:37:04 EDT 2018
[root@slave1 logs]# mv /etc/localtime /etc/localtime.bak
[root@slave1 logs]# ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[root@slave1 logs]# date
Wed Aug 29 09:41:07 CST 2018