一 shell 中的函数

1 先了解脚本的几个系统变量

$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

2 函数的定义及用法
函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这个小单元的名字即可。格式: function f_name() { command }函数必须要放在最前面,其中关键字function可以省略
示例1

vim 6.sh
#!/bin/bash
input() {
    echo $1 $2 $# $0
}
input 4 4 4 4 4

sh执行结果为: 4 4 5 6.sh
$1 $2 标示传递给shell脚本的第一个,第二个参数
$# 标示传递给脚本的参数个数
$0 是脚本本身的名字,如果用./执行的话,$0会跟执行脚本时所在路径。
示例2

#!/bin/bash
sum()
{
s=$[$1+$2]
echo $s
}
sum 1 2

如果要在脚本外面传入参数,sum 1 2 可以改为sum $1 $2,然后执行脚本时带上参数,比如 sh sum.sh 1 2
示例3
需求,写一个脚本,给出网卡名称,就能显示对应的ip地址
脚本调试
ifconfig |grep ens33 -A1 |grep 'inet' |awk '{print $2}'
也可以写成
ifconfig |grep ens33 -A1 |awk '/inet/ {print $2}'
各段含义:
ifconfig 不用说了,可以查看网卡相关信息
grep enss3 -A1 过滤出含有网卡名称ens33 的行,并顺带打印其下一行。也就是我们需要的ip地址行
grep 'inet' 找出还有ip地址的行,这里可以使用tail -1代替
awk '{print $2}' 打印ip地址行的第二段,也就是ip地址了,awk不指定分隔符,默认以空格或者tab分割。也就是以空字符分割。
最终结果

#!/bin/bash
ip()
{
ifconfig |grep "$1: " -A1 |grep 'inet' |awk '{print $2}'
}
read -p "please input a name of network card: " name
ip $name

备注:grep命令后面的$1表示函数传递的第一个参数,一定要用双引号。
对上面脚本做一个完善,
1 判断该网卡名是否为系统里的网卡,不是给出提示
2 判断该网卡是否分配了ip地址,没有给出提示

#!/bin/bash
ip()
{
ifconfig |grep "$1: " -A1 |grep 'inet'|awk '{print $2}'
}
read -p "please input a name of network card: " name
ip $name
n=`ifconfig |grep "$name"`
if [ -z "$n" ];then
    echo "the eth is not exist"
fi
m=`ifconfig |grep "$name" -A1 |grep 'inet'`
if [ -z "$m" ];then
    echo "the eth has no ip assigned"
fi

二 shell中的数组

定义数组 a=(1 2 3 4 5)
echo ${a[@]} // 显示整个数组,等价于echo ${a[*]}
echo ${#a[@]} 获取数组的元素个数
echo ${a[2]} 读取第三个元素,数组元素编号从0开始
数组赋值
a[1]=100; echo ${a[@]}
a[5]=2; echo ${a[@]} 如果下标不存在则会自动添加一个元素
数组的删除
unset a[1] ;echo ${a[*]} //删除数组中第1个元素
unset a;echo ${a[*]} //清空数组
数组分片
a=(`seq 1 5`)
echo ${a[@]:0:3} 从第一个元素开始,截取3个
echo ${a[@]:1:4} 从第二个元素开始,截取4个
echo ${a[@]:0-3:2} 从倒数第3个元素开始,依次向后截取2个
数组替换
echo ${a[@]/3/100} //将数组a中的3替换成100(只显示到屏幕,并不更改数组)
a=(${a[@]/3/100}) //将数组a中的3替换成100 ( 更改数组)