linux shell编程基础

*shell脚本执行的方式:

    脚本文件要在第一行头部以相应的格式写明bash的路径,例,#!/bin/bash

  • 给予脚本文件执行权限,输入文件的路径,进行执行

    • 例,/scripts/first.sh

  • 将脚本文件作为bash的参数,交由bash解释器执行

    • 例,bash /scripts/first.sh,这种方法不需要赋予文件执行权限。

  • 还可以使用shell内置命令source/.执行,source和 . 功能相同

    • source test.sh或 . test.sh

 

*逻辑运算符

  • bash shell支持短路运算:

    • 例,ls /  ||  echo success,如果第一个执行成功,则整个或运算都是成功的,第二命令则不会再去执行。如果第一个执行失败,bash才会去执行第二个命令。

    • 例,ls /gsg && echo failure ,如果第一个执行失败,则整个与运算都是错的,第一个命令不会再执行。相反,如果第一个执行成功,则会再执行第二个。

    • 简单运用,ls /sd &> /test/out && echo success || echo failure ,如果第一个命令执行成功则输出succsee,否则输出failure。

*算数运算:

  •  如果直接这样定义:count=1 $count=$count+1,最后得到的count=1+1,而不是2,要是想执行算数运算需要这样:$count=$[$count+1],这样得到的count才是2

  • let命令:使用这个命令可以直接执行命令后面的算数式,let后面的变量名不需要加$。

    • 例,let count+=1,或count=1 x=5 let count+=x。

*bash中的变量种类:

  • 本地变量:生效范围仅限当前shell进程,其子进程也无效。

  • 环境变量:生效范围是当前shell进程及其子进程

  • 局部变量:生效范围为当前shell进程中某代码片段(通常指函数)

  • 位置变量:$1,$2,$...,用户让脚本在脚本代码中调用命令行传给的参数。

    • 例,新建一个b.sh文件,内写a=$1 b=$2 echo $a echo $b,然后不加参数执行,什么都不会输出。

    • 这样,./b.sh x y 执行,会输出x和y,相当于把x赋给了a,把y赋给了b。

  • 特殊变量:$?,$0等等

*位置变量

  • 使用:$1,$2...分别对应传给脚本的第1,2...个参数。

  • 注:如果位数大于一需要使用{}包起来,例${10},不然shell会把它当做$1处理。

  • shift命令:他可以去掉传给脚本的参数。

    • 格式:shift n,n表示数字,n为几,就会去掉前几个参数,见代码:

b.sh:

    echo $1            #输出第一个参数tom

    shift 1               #去掉了第一个参数

    echo $1            #此时her就成了第一个参数,所以会输出her

[root@VM1 scripts]$ ./b.sh tom her

tom

her
  • $0:命令本身

  • $*:传递给脚本的所有参数,加了引号之后,它会把所有的参数当做一个字符串处理

  • $@:传递给脚本的所有参数,加了引号之后,它把每个参数都当做单个字符串。

  • $#:传递给脚本的所有参数的个数

  • 还有$$(获取当前shell的进程号PID),$!(上一个命令的PID),$?(查看上一个命令的执行状态,0为成功,非0失败),$_(上个命令的最后一个参数)

 

*变量的赋值、引用、销毁

  • 变量赋值:

    • 本地变量:

      • 直接字符串赋值:name="user1"

      • 变量引用:name="$变量名"

      • 命令引用:name=`命令`(注:反引号)或name=$(命令),会将命令的执行结果赋给变量

    • 环境变量:环境变量的定义即把定义好的本地变量导出为环境变量

      • export 变量

      • declare -x 变量

    • 只读变量:

      • 可以使用declare -r ,变量的格式将本地变量变成只读变量

      • 只读变量不能被修改,不能被销毁,随当前shell进程的销毁而销毁。

  • 变量引用:使用${name}的方式引用,一般情况{}可以省略,$后直接加变量名。

    • "":弱引用,其中的变量引用会被替换为变量值。

    • '':强引用,其中的变量引用不会被替换为变量值,而是保留原字符串。

    • 变量引用时也可以不加引号,默认是弱引用

[root@VM1 scripts]# a="num"

[root@VM1 scripts]# b=$a

[root@VM1 scripts]# c='$a'

[root@VM1 scripts]# d="$a"

[root@VM1 scripts]# echo $b

num

[root@VM1 scripts]# echo $c

$a

[root@VM1 scripts]# echo $d

num
  • 变量销毁:unset 变量名,使用set命令可以查看已定义的所有变量,使用export/env/printenv查看环境变量

 

*条件测试:

    测试某需求是否满足,这就需要我们的测试机制来实现。

  • test命令:或[ expression ]或[[ expression ]],这样与test命令效果一样。注:这里[ ]内的表达式与括号直接必须有空格

    • 格式:test expression

    • test命令是不会有任何输出的,所以我们需要通过echo $?来查看上一条命令的执行状态,如果是1,则说明测试失败,如果是0,则说明测试成功。

    • 例,test 1 -gt 8,然后通过echo $?查看执行状态,结果为1,则说明测试失败即1不大于8。

  • bash的测试类型

    • 数值测试:

      • -gt:是否大于

      • -ge:是否大于等于

      • -eq:是否等于

      • -ne:是否不等于

      • -lt:是否小于

      • -le:是否小于等于

    • 字符串测试:

      • ==、>、<、!=不再赘述

      • =~:左侧字符串能否被右侧的正则表达式匹配,一般用于[[  ]]内

      • -z:后跟字符串,测试字符串内容是否为空,空为真,不空为假

      • -n:后跟字符串,测试字符串内容是否为空,空为假,不空为真

    • 文件测试:

      • -a:判断文件是否存在,存在为真,不存在为假

      • -e:同上

      • -d:判断是否存在且为普通文件

      • -f:判断是否存在且为目录文件

      • -s:判断文件是否存在且非空

*程序分支:

  • if-elif-else:

if condition1

then

command1

elif condition2

then

command2

else

commandN

fi
  • case语句:

case 值 in

模式1)

command

;;

模式2)

command

;;

esac

示例:

#!/bin/bash

i=$1

case $i in

1)

    echo "input is 1"

    ;;

2)

    echo "input is 2"

    ;;

esac

echo "done"
  • 需求:写一个脚本要求用户给一个参数,根据参数判断此用户是否存在,如果不存在则添加用户,并设置密码与用户名相同。

#!/bin/bash

if [ $# -lt 1 ]; then

    echo "至少给一个参数"

    exit 1

fi

if id $1 &>/dev/null ;then

    echo "用户已存在"

else

    useradd $1

    [ $? -eq 0 ] && echo "$1"| passwd --stdin $1 &> /dev/null

    echo "用户添加成功"
fi

 

*循环

    shell实现循环有三种方式,可以与continue,break等控制语句一块使用:

  • for:可以遍历

#!/bin/bash

for i in $*;do        #遍历输出所有参数

    echo $i

done

for i in {1..10};do    #遍历1到10

        echo $i

done
  • while:while是当判断为true时去执行循环体,直至条件不满足

#!/bin/bash

# 计算1到100的和

declare -i i=0

declare -i sum=0

while [ $i -lt 100 ];do

    let sun+=$i

    let i++

done

echo "sum:$sum"
  • until:until是判断为false时去执行循环体,直至条件不满足

#!/bin/bash

# 计算1到100的和

declare -i i=0

declare -i sum=0

until [ $i -gt 100 ];do

    let sun+=$i

    let i++

done

echo "sum:$sum"

 

*shell中的数组

  • 数组的定义 在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。

    • 例,array=(java spring python shell linux sql "spring boot")

    • 若是元素内也有空格,则必须使用引号

  • 数组的赋值

    • 直接赋值:array=(java spring python shell linux sql "spring boot")

    • 只给某个元素赋值:

      • array[1]=cvb;array[4]=bdc

      • array=([0]=java [2]=spring)

#!/bin/bash

#生成10个随机数赋给一个数组,并求出最大值

max=0

for i in {0..9};do

    array[$i]=$RANDOM        # $RANDOM可随机生成一个1到32767的数字

    echo ${array[$i]}

    [ ${array[$i]} -gt $max ] && max=${array[$i]}

done

echo "MAX:$max"
  • 读取数组

    • 直接输出数组:echo $array,会直接输出数组的第一个元素,即java,这里与c很像

    • 根据下标输出:echo $array[2],下标从0开始。

    • 下标也是变量:echo ${array[$i]},即根据变量i输出数组的内容

  • 获得数组的长度:echo ${#array[*]}或echo ${#array[@]}

    • 同样的,获得数组内某个元素的长度:echo ${#array[$i]}

  • 输出数组的所有元素echo ${array[*]},也可以使用@符号,它与获得数组长度就是差了#号。

    • 加#号就是计算长度,不加就是输出值。

  • 数组切片

    • ${array[@]:offset:number}:表示从下标为offset开始取,取number个元素

    • ${array[@]:offset}:从下标为offset开始取,取到数组最后

  • 向数组中追加元素:array[${#array[*]}]=value

  • 删除数组中某个元素:unset array[index],删除后这个位置会变成空

*shell字符串的操作

  • 字符串切片:

    • ${str:offset:number}:从offset开始取,取number个

    • ${str: -length}:从字符串右侧开始取,取length个

  • 字符串截取子串,声明str=/temp/data/sc,用作示例

    • ${str#*word}:从左到右,查找str字符串中第一次匹配到的word字符,删除字符串开头到第一次出现word的地方之间的所有字符。

      • 例,${str#*t},输出:emp/data/sc

    • ${str##*word}:同上,不过是删除从字符串开头到最后一次匹配到word的地方。

      • 例,${str##*t},输出:a/sc

    • ${str%word*}:从右至左,查找str字符串中第一次匹配到的word字符,删除字符串的最后一个字符到word第一次出现的地方之间的所有字符串。

      • 例,${str%t*},输出:/temp/da

    • ${str%%word*}:同上,不过是删除从最后一个字符串到最后一次匹配到word字符之间的所有字符串。

      • 例,${str%%t*},输出:/

  • 字符串的查找替换:user=$(head -1 /etc/passwd),即user=root:x:0:0:root:/root:/bin/bash

    • ${str/pattern/replace}:查找str所表示的字符串中第一次被pattern匹配的字符串,替换成replace

      • echo ${user/root/ROOT},输出:ROOT:x:0:0:root:/root:/bin/bash

    • ${str//pattern/replace}查找str所表示的字符串中所有被pattern匹配的字符串,替换成replace

      • echo ${user//root/ROOT},输出:ROOT:x:0:0:ROOT:/ROOT:/bin/bash

    • ${str/#pattern/replace}:查找行首被pattern匹配的字符串,并使用replace替换匹配到的字符串

    • ${str/%pattern/replace}查找行尾pattern匹配的字符串,并使用replace替换匹配到的字符串

  • 字符串的删除:

    • ${str/pattern}:删除第一次被pattern匹配到的字符串。

    • ${str//pattern}:同查找替换

    • ${str/#pattern}:同上

    • ${str/%pattern}:同上

  • 字符的大小转换:

    • ${str^^}:把str中所有小写字母转换成大写

    • ${str,,}:把str中所有大写字母转换成小写

  • 变量的赋值:

    • ${str:-value}:如果变量str为空或不存在,返回value,否则返回str的值。

    • ${str:=value}如果变量str为空或不存在,把value的值赋给str,并返回。否则返回str的值

    • ${str:+value}:如果变量str不为空,则返回value,否则,什么也不做。

    • ${str:?error_info}如果变量str为空或不存在,则返回错误信息。是以错误输出流的方式返回。否则,返回str的值。

*read命令:

    read命令可以用在脚本中做交互

  • 简单示例:echo "Enter name";read name,这样shell会把用户输入的数据赋给name变量

  • 常用选项

    • -p:设置文字提示

      • 例,read -p "Enter name:" name,效果同上,不过输出提示语句后不会换行

    • -t:设置过期时间,read在等待用户输入数据时不可能无止境的等待,可以设置等待时间。

  • 主要用于脚本中,与用户做交互,例:

#!/bin/bash

read -p "Enter Username:" name

useradd $name

echo "Useradd success"

*printf命令

    它是模仿c里面的printf 语句,相比echo有更好的移植性。

  • 格式替代符:

    • %s:字符串

    • %c:字符

    • %f:浮点数

    • %d:整数

    • 例,printf "%d-%s \n" 1 asd,输出:1-asd并换行

  • 转义字符序列:

    • \a:警告字符,通常为ASCII的BEL字符

    • \b:回退

    • \c:抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略

    • \f:换页

    • \n:换行

    • \r:回车

    • \t:水平制表符

    • \v:垂直制表符

*shell函数

  • 函数定义:有两种方法:

function 函数名{

    函数体

}

函数名(){

    函数体

}

示例:

#!/bin/bash


function print {

        echo $str

}

for i in {1..10};do

        str=hello$i

        print

done
  • 给函数传参:和给脚本传参一致,在函数后面以空格分割给定参数列表即可。

    • 然后在函数中以使用位置变量的方式引用传给函数的参数即可。也支持特殊变量。

  • 局部变量:在函数中定义局部变量要使用local关键字

  • 返回值:函数的返回值即函数中最后一条语句的返回值

     

*在脚本程序中读取配置文件

  • 首先定义配置文件

  • 然后在脚本中source此文件

  • 示例:

配置文件t.conf内:

HOST=WUUU


脚本文件内:

#!/bin/bash

[ -r /scripts/t.conf ] && source /scripts/t.conf

MYHOSTNAME=$HOST

echo $MYHOSTNAME


输出:WUUU

 

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值