shell编程

1,shell脚本的变量认识

变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数,n是一个数字,表示第几个参数。例如第一个参数是$1,第二个参数是$2
$# 表示传递给脚本或者参数的个数
$* 传递给脚本或函数的所有参数
$@ 传递给函数互脚本的所有的参数,被双引号(“ ”),与$*稍有不同
$? 上个命令的退出状态,或函数的返回值
$$ 当前shell进程id。对于shell脚本,就是这些脚本所在的进程id
  • 注释:$*和$@的区别:
    • $*和$@都表示传递给函数或脚本的的所有的参数,不被双引号(“ ”)包含时,都以$1,$2,$3。。。$n的形式输出所有参数,但他们被双引号(“ ”)时,$*会将所有参数作为一个整体,以“$1, $2,$3...$n”的形式输出,$@会将各个参数分开,将以“$1”,“$2”,“$3”。。。“$n”的形式输出

2,一个简单的shell脚本文件

a="雪雪"
echo  "$a is my favourite"

  • 注意:在定义变量和给变量赋值的时候,变量名和=之间不能有空格,=和变量之间也不要有空格

3,逻辑控制语句

a="雪雪"
echo  "$a is my favourite"
if [ -n "$a" ];then
echo "$a long time no see"
else
echo "$a i miss you"
fi
# 语法结构
# if [ 条件 ];then
# 代码块
# else
# 代码块
# fi 结束if语句

# 基本的条件判断
# [ -f "somefile" ]:判断是否是一个文件
# [ -x "/bin/ls" ]:判断/bin/ls是否存在,并有可执行权限
# [ -n "$var" ]:判断var变量是否有值
# [ "$a" = "$b" ]:判断$a和$b是否相等
# [ ]

  • 注意:在写if,else逻辑控制语句的时候if和条件用空格隔开,条件用[]包裹起来[]后边要跟;(不是冒号:一定要分清);后边要跟then,然后是业务逻辑部分else,后边是否则的业务逻辑的部分,最后要加上fi结束if语句
mailfolder=~/hello/readme.txt
if [ -r "$mailfolder" ];then
    echo "$mailfolder has mail from : "
    echo | grep "^echo" $mailfolder >> readme2.txt
    chmod +r readme2.txt
    cat readme2.txt >> $mailfolder
    rm -f readme2.txt
else
    echo "can not read $masifolder"
    touch $mailfolder
    chmod +rw $mailfolder
    echo "echo 世情薄,人情恶,雨送黄花花易落,晓风干, 泪痕残。欲笺心事,独倚斜栏, 难,难,难!
    人成各,今非昨, 病魂常似秋千索,角声寒,夜阑珊,怕人询问,咽泪装欢,瞒,瞒,瞒。"
fi

4,while循环的shell代码

f1=/etc/passwd
count=`cat $f1 | wc =l`
# 下面是一个管道,下面循环读取文件中的每一行
cat $f1 |
while read line
do
    user= "echo $line|awk -F ':' '{print $1}'"
    # 代表以:分段$1就是取第一段
    uid="echo $line|awk -F ':' '{print $3}'"
    echo "hello, $user your uid is $uid"
done
echo "====User_count:$count===="

  • 注释:awk是行处理器,awk -F,处理行指定分隔符,wc(word count)是Linux中统计指定文件的字节数、字数、行数等计数用的

5,for循环的代码编写

需求:

  • 切换至工作目录/tmp
  •  一次向每个子目录下的文件或者子目录问好
  • 统计/tmp目录下有多少个文件并统计出来
cd /tmp
for i in /tmp/*
do
    echo "hello,$i"
done
count="ls -l|grep '^-'|wc -l"
echo "====file_count:$count===="

***我写的第一版:遇到一个问题,就是在count计数的时候,用饿的是英文的双引号("")结果,就是计数不成功

我写的第二版

# cd /tmp    # 把进入到/tmp目录下这个注释掉
for i in /tmp/*
do
    echo "hello,$i"
done
count=`ls -l|grep '^-'|wc -l`
echo "====file_count:$count===="

###我把进入到/tmp目录下这行代码注释掉,并把count计数用反引号包裹起来,计数就生效了,而且计数是9个文件

第三版:将cd /tmp注释打开

cd /tmp    # 把进入到/tmp目录下这个注释掉
for i in /tmp/*
do
    echo "hello,$i"
done
count=`ls -l|grep '^-'|wc -l`
echo "====file_count:$count===="

  • 此时对于文件的计数就是1个。

6,给shell脚本传递参数,

# 给shell脚本传递整数,让脚本计算穿进去整数的和,积,差,商
a=$1
b=$2

# 表示如果$a字符串为空,就输出please $1 number1
[ -z $a ] && echo "please $1 number1" && exit 1
# 表示如果$b字符串为空,就输出please $2 number2
[ -z $b ] && echo "please $2 number2" && exit 2
# 表示这个脚本需要传递2个参数
[ ! $# -eq 2 ] && echo "--please num1 num2"  && exit 3
# $#是表示传递给脚本的参数的个数
# -eq相当于=,-ne相当于不等于, -ge >=,-gt >,le <=, -lt <
echo "$a + $b = $(($a+$b))"
echo "$a - $b = $(($a-$b))"
echo "$a * $b = $(($a*$b))"
echo "$a / $b = $(($a/$b))"

  • 注意:传递参数的时候,中间不要加逗号(,)这样系统会认为前两个数是一样的,只会把逗号(,)前后2个接近的数进行运算

判断语句的知识点:

  1. 文件表达式 
    1. if [ -f file ]:表示如果文件存在
    2. if [ -d ... ]:表示如果目录存在
    3. if [ -s file ]:表示如果文件存在且非空
    4. if [ -w file ]:表示如果文件存在且可写
    5. if [ -r file ]:表示如果文件存在且可执行
  2. 整数变量表达式
    1. if [ int1 -eq int2 ]:表示如果int等于int2
    2. if [ int1 -ne int2 ]:表示如果int1不等于int2
    3. if [ int1 -ge int2 ]: 表示如果int1大于等于int2
    4. if [ int1 -gt int2 ]:表示如果int1大于int2
    5. if [ int1 -le int2 ]:表示如果int1小于等于int2
    6. if [ int1 -lt int2 ]:表示如果int1小于int2
  3. 字符串变量表达式
    1. if [ $a=$b ]:如果string1等于,字符串允许使用赋值号作为等号(=)
    2. if [ $string1 != $string2 ]:如果string1不等于string2(!=)
    3. if [ -n $string ]:如果string非空(非0),返回o(true)
    4. if [ -z $string ]:如果string为空
    5. if [ $string ]:如果字符串非空,返回0(和-n类似)
  4. 在shell编程中:&&与||的区别
    1. cmd1 && cmd2:(类似if 条件)
      1. 若cmd1执行完毕且执行正确,才开始执行cmd2
      2. 若cmd1执行完毕且执行错误,则cmd2不执行
    2. cmd1 || cmd2:(类似if not 条件)
      1. 若cmd1执行完毕且执行正确,cmd2也不会执行
      2. 若cmd1执行完毕且执行错误,cmd2则开始执行

7,编写脚本计算从1到100的和

sum=0
i=1
while [ $i -le 100 ]  # 再次强调条件和[ 条件 ]之间一定要用空格隔开
do
    sum=$(($sum+$i))  # 坑:运算的时候要用$(($a+$b))
    i=$(($i+1))
done
echo "$sum"

for 循环的饿从1加到100

sum=0
for ((i=1;i<=100;i++))  # 用for循环的时候要用(())包裹起来,之间的元素有分号(;)隔开
do
    ((sum=sum+i))  # 结果还是得用(())包裹起来
done
echo "$sum"

8,shell函数的编写

  • 函数编程的语法:
# 第一种
function 函数名(){
       指令。。。
       return -n    
}
# 第二种
function 函数名{
        指令。。。
        return -n
}
# 第三种
函数名 (){
        指令
        return -n
}
  • 注释:function表示声明一个函数,return -n是指退出函数
# shell函数的编写
function xuexue () {  # 函数的声明是一个function,函数名叫xuexue(){}
    echo "世情薄,人情恶, 雨送黄昏花易落,晓风干,泪痕残,欲笺心事,独语斜栏。难,难,难!"  # 函数的代码块
    echo "唐婉"
}  # 函数的闭合区间

function xiaoxue(){  # 函数的声明是function,函数名叫做xiaoxue)_{}
    echo "人成各,今非昨,病魂常似秋千索,角声寒,夜阑珊,怕人询问,咽泪装欢。瞒,瞒,瞒!"  # 函数功能的代码块
    return  # 退出函数
    echo "月亮很亮"
}   # 函数的闭合区间

xuexue  # 调用xuexue这个定义的函数

xiaoxue  # 调用xiaoxue这个定义的函数

9, 分离函数体执行函数的脚本文件

  • 第一步向将函数写入指定的文件中
cat >>~/hello/functions<<EOF
function xuexue(){
    echo "世情薄,人情恶,雨送黄昏花易落,晓风干,泪痕残,欲笺心事,独语斜阑。难,难,难!"
}
EOF
    • 表示把函数xuexue,导入到~/hello/functions中
  • 第二步执行命令把把函数写到指定的卢金过得文件中

我们可以清除的看到,函数已经被写入到指定的文件中了,下面我们可以在另外一个文件调用函数了

if [ -f ~/hello/functions ]
    then
        . ~/hello/functions
fi

xuexue

切记:切记,.在这里表示加载functions(文件)中的命令或者变量参数等,.和后边的路径一定要有空格,然后我们运行这个脚本就可以了

小结:当我们定义大量函数的时候,我们就可以把函数写在某一个函数中,当我们写脚本的时候,需要其中的某一个函数的时候,我们就可以直接调用文件中的函数名

10,编写待参数的函数实例

function xueren(){
    echo "我的名字叫:$1,我喜欢:$2"
}
xueren $1 $2

11,闭包函数

a=1
function outter(){
    a=2
    function inner(){
        echo "这是什么啊"$a 
    }
    inner
    echo $a
}
echo $a
outter

运行代码输出:

12,利用shell函数开发企业级url检测脚本

#!/bin/bash  
#no.1  
if [ "$#" -ne 1 ]              #如果用户输入的传参参数不是1  
  then          # 那么    
      echo "/root/sh/ $0" 请您输入一个网址  #输出脚本路径和脚本名称 最后输出请您输入一个网址!  
      exit 1            #退出脚本  
fi              #结束  
#no.2  
wget --spider -q -o /dev/null --tries=1 -T 3 $1 #如果用户输入传参数是对的,那么执行wget命令最后$1是用户输入的内容  
if [ "$?" -eq 0 ]    #如果以上wget测试成功了!  
  then  #那么  
    echo "$1 检测是成功的!"  #输出用户输入网址并输出是成功的  
  else  #否则  
    echo "$1 检测是失败的!"  #输出用户输入网址并输出是失败的  
    exit 1      #退出脚本  
fi    #fi结束

很尴尬,我检测都是失败的。

原文地址:https://www.cnblogs.com/ljc-0923/p/10988414.html