目录
自定义函数
递归-自己调用自己
上机练习 12
Shell 工具
sort
sed
awk
上机练习 13
自定义函数
name(){
action;
}
function name
{
Action;
}
name
因为 shell 脚本是从上到下逐行运行,不会像其它语言一样先编译,所以函数必
须在调用
之前,先声明。
函数返回值,return 后只能跟数值 n(0-255)
接收返回值方法:在函数内部使用 echo 命令将结果输出,在函数外部使用$()
或者``捕获
结果。
# 无输入无返回
hello (){
echo "test"
}
hello
# 写一个自定义函数,计算两个输入参数的和
he (){
s=0
s=$(( $1 + $2 ))
echo " $s "
}
he 3 65
jieguo=`he 3 65`
echo " 和是: $jieguo "
可以输入参数
read -p " 请输入第一个数: " n1
read -p " 请输入第二个数: " n2
jieguo=`he $n1 $n2`
echo " 和是: $jieguo"
# 也可以使用 shell 位置参数传递到函数 可以互相调用
he(){
date
hello
s=0
s=$(($1 + $2))
echo "$s"
}
递归-自己调用自己
# 输入一个目录显示里面的所有目录
fun(){
for i in `ls $1`
do
if [ -d $1/$i ]
then
echo $i
fi
done
}
fun /root
# 输入一个目录显示里面的所有目录及其子目录
echo $i
fun $1/$i
上机练习 12
# 1. 编写函数 , 函数传入三个参数 , 输出积
# product()
# {
#
p=$(($1*$2*$3))
#
echo $p
# }
# product 2 4 5
# 2. 编写函数,传递一个数字参数 5 ,实现 1 到 5 的累加,返回和,输出 " 和是:
15"
# sum()
# {
#
sum=0
#
for i in `seq 1 $1`
#
do
#
sum=$(($sum+$i))
#
done
#
echo " 和是 $sum" # }
# sum 5
# sum 6
# sum 10
# 3. 编写函数 , 当该函数没有参数或参数多于 2 个 , 输出 -1, 只有一个参数时 , 输出
1, 有两个参数
# 时 , 输出 2
# 提示:使用 $# 判断参数的个数
# nnumber()
# {
#
if [ $# -gt 2 -o $# -eq 0 ]
#
then
#
echo -1
#
else
#
echo $#
#
fi
# }
# nnumber
# nnumber 1
# nnumber 1 2
# nnumber 1 2 3
# 4. 编写函数,实现传入一个目录参数,将该目录下(递归)所有的文件都打印
出来(遇
# 到文件则打印,遇到目录则继续调函数递归)
# PrintFile()
# {
#
if [ -d $1 ]
#
then
#
for i in `ls $1`
#
do
#
if [ -f $i ]
#
then
#
echo "$1/$i"
#
else
#
PrintFile $i
#
fi
#
done
#
else
#
echo $1
#
fi
# }
# PrintFile /root
# PrintFile age.txt
# 5. 编写函数,传入一个数字 n ,实现 n 的阶乘 , 效果如下: # factorial()
# {
#
echo " 请输入数字 :$1"
#
echo -n " 根据数字 ${1} 得到的阶乘表达式是: $1!="
#
f=1
#
for i in `seq $1 -1 1`
#
do
#
echo -n $i
#
if [ $i -eq 1 ]
#
then
#
echo -n "="
#
else
#
echo -n "*"
#
fi
#
f=$(($f*$i))
#
done
#
echo $f
# }
# factorial 4
# factorial 5
# factorial 6
Shell 工具
sort
sort 命令是在 Linux 里非常有用,它将文件进行排序,并将排序结果标准输出。
参数:指定待排序的文件列表
shell 下面建立如下文件 sort.txt bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
按照“:”分割后的第三列倒序排序。
sort -t ":" -nrk 3 /root/shell/sort.txt
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6
grep 、 sed 、 awk 被称为 linux 中的 " 三剑客 " 。
我们总结一下这三个 " 剑客 " 的特长。
grep 更适合单纯的查找或匹配文本
sed 更适合编辑匹配到的文本
awk 更适合格式化文本,对文本进行较复杂格式处理
sed
sed: stream editor (流编辑器)的简称。
它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中( “ 模式空
间 “ ),
接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。
接着处理
下一行,这样不断重复,直到文件末尾。
p 打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
i 插入, i 的后面可以接字串,而这些字串会在新的一行出现 ( 目前的上一行 ) ;
a 新增, a 的后面可以接字串,而这些字串会在新的一行出现 ( 目前的下一行 )
s 取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!
1. 显示文件的第 2 行的内容:
sed -n '2 p' /root/shell/sort.txt
2. 显示文件的第 2 行到第 4 行的内容:
sed -n '2,4 p' /root/shell/sort.txt
3. 将文件中的 bb 全部替换为 BB
sed 's/bb/BB/g' /root/shell/sort.txt
4. 以文件 bb 开头的上一行添加
sed '/^bb/i hello' /root/shell/sort.txt
5. 将文件中的 d 全部删除
sed 's/d//g' /root/shell/sort.txt
注:可以使用管道符连续处理 , 接着重定向保存,使用 \ 拼接换行
awk
一个完整的 awk 命令形式如下:
awk [options] 'BEGIN{ commands } { commands } END{ commands }' file
-v 指定 FS 和 OFS 字段分隔符和输出字段分隔符
内置参数:
NF 分割完字段的数量
$1 代表文本行中的第 1 个数据字段;
$2 代表文本行中的第 2 个数据字段;
输出指定列: {print $1,$2}
分隔符相同的情况输出一整行: {print}
1. 以 : 为分隔符,打印第 2 列和第 1 列
awk -v FS=":" '{print $2,$1}' /root/shell/sort.txt
2. 以 : 为分隔符,打印第 2 列和第 1 列,列之间用 , 分割
awk -v FS=":" -v OFS="," '{print $2,$1}' /root/shell/sort.txt
3. 添加列保存为 csv ,下载,使用 excel 查看
awk -v FS=":" -v OFS="," 'BEGIN{print "one,two,three"}{print $2,$1,$3}'
/root/shell/sort.txt > /root/shell/sort.csv
4. 第二列大于 30
awk -v FS=":" '{ if($2>30){print $2}}' /root/shell/sort.txt
5. 行列总数量
awk -v FS=":" 'BEGIN{n=0}{for(i=1;i<=NF;i++){n++} }END{print n}'
/root/shell/sort.txt
注:可以使用管道符连续处理 , 接着重定向保存,使用 \ 拼接换行
上机练习 13
# 创建 shell 脚本来完成
# 1.复制网卡文件/etc/sysconfig/network-scripts/ifcfg-ens33 到家目录,
并且改名为
# wangka.txt
# cp /etc/sysconfig/network-scripts/ifcfg-ens33 /home/
# mv /home/ifcfg-ens33 /home/wangka.txt
# 2.找到含有 IP 的行输出
# cat -sb /home/wangka.txt | grep "IP"
# 3.显示文件的第 3 行到第 5 行的内容
# sed -n "3,5 p" /home/wangka.txt
# 4.将文件中的 255 全部替换为 250
# sed 's/255/250/g' /home/wangka.txt
# 5.以文件 IPADDR 开头的上一行添加 hello
# sed '/^IPADDR/i hello' /home/wangka.txt
# 6.找到所有 DNS,并且删掉
# sed 's/DNS//g' /home/wangka.txt
# 7.使用管道符连续处理 4. 5. 6. 题,并且重定向结果保存为 wangka.csv # sed 's/255/250/g' /home/wangka.txt | sed '/^IPADDR/i hello' | sed
's/DNS//g' > /home/wangka.csv
# 8. 根据 wangka.csv 文件自己灵活处理重定向为 ip.txt,内容如下:
# 192.168.145.151
# 250.250.250.0
# 192.168.145.2
# 8.8.8.8
# 114.114.114.114
# sed -n '19,23 p' /home/wangka.csv | awk -v FS="\"" '{print $2}' >
/home/ip.txt
# 9. ip.txt 中以.分割,按照第一列进行降序排序
# sort -t "." -nrk 1 /home/ip.txt
# 10. ip.txt 中以.为分隔符,打印第 1 列和第 2 列
# awk -v FS="." '{print $1,$2}' /home/ip.txt
# 11. ip.txt 中以.为分隔符,打印第 3 列和第 4 列,列之间用,分割
# awk -v FS="." -v OFS="," '{print $3,$4}' /home/ip.txt
# 12. ip.txt 中以.为分隔符,列之间用,分割,且加一行,保存为 ip.csv,格式
如下:
# one,two,three,four
# 192,168,145,151
# 250,250,250,0
# 192,168,145,2
# 8,8,8,8
# 114,114,114,114
# awk -v FS="." -v OFS="," 'BEGIN{print "one,two,three,four"}{print}'
/home/ip.txt > /home/ip.csv
# 13. 在家目录下创建一个 names.txt 的文件,写入班级的所有同学的姓名,每
个一行,每
# 次随机产生一个姓名
# 终端执行
# touch /home/names.txt
# vim /home/names.txt
# i 编辑模式
# 输入
# ESC
# :wq!
# shell 执行
# sed -n "$(($RANDOM%12+1)) p" /home/names.txt
# 14. 批量修改家目录下的文件扩展名,使用位置参数传递两种扩展名,例如
txt 文件为 csv
# 文件。(注:碰到特殊符号使用\进行转义)
# UpdateType()
# {
# ls /home > /root/updatefile.txt # sed "s/.$1/.$2/g" /root/updatefile.txt > /root/updatefile1.txt
# count=1
# for i in `ls /home`
# do
#
f=$(sed -n "$count p" /root/updatefile1.txt)
#
echo $f
#
if [ /home/$i != /home/$f ]
#
then
#
mv /home/$i /home/$f
#
fi
#
count=$(($count+1))
# done
# echo "重命名扩展名成功"
# }
# UpdateType csv txt
最后一题想了好久,终于写出来了,shell是真的阴间。
愉快的双休又来喽!