目录
自定义函数
递归-自己调用自己
上机练习 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是真的阴间。
愉快的双休又来喽!