【Shell脚本编程(一)】变量的高级用法

1. 变量替换

语法说明
${变量名#匹配规则}从变量开头进行规则匹配,将符合最短的数据删除。
${变量名##匹配规则}从变量开头进行规则匹配,将符合最长的数据删除。
${变量名%匹配规则}从变量尾部进行规则匹配,将符合最短的数据删除。
${变量名%%匹配规则}从变量尾部进行规则匹配,将符合最长的数据删除。
${变量名/旧字符串/新字符串}变量内容符合旧字符串则,则第一个旧字符串会被新字符串取代。
${变量名//旧字符串/新字符串}变量内容符合旧字符串则,则全部的旧字符串会被新字符串取代。

例子1:

variable_1="I love you, Do you love me"

var1=${variable_1#*ov}
var2=${variable_1##*ov}

var3=${variable_1%ov*}
var4=${variable_1%%ov*}

echo $PATH
var5=${PATH/bin/BIN}
var6=${PATH//bin/BIN}

2. 变量测试

变量配置方式str没有配置str为空字符串str已配置且非空
var=${str-expr}var=exprvar=var=$str
var=${str:-expr}var=exprvar=exprvar=$str
var=${str+expr}var=var=exprvar=expr
var=${str:+expr}var=var=var=expr
var=${str=expr}var=exprvar=var=$str
var={str:=expr}var=exprvar=exprvar=$str

3. 字符串处理

3.1. 计算字符串长度

方法语法说明
方法一${#string}
方法二expr length “$string”string中有空格,则必须加双引号。

例子:

var1="Hello World"
#方法一
len=${#var1}

#方法二
len='expr length "$var1"'
echo $len  #结果为11

3.2. 获取子串在字符串中的索引位置

语法expr index $string $substring

例子:

var1="quickstart is a app"
ind='expr index "$var1" start'
echo $ind  #结果为6

ind='expr index "$var1" uniq'
echo $ind  #结果为1

ind='expr index "$var1" cnk'
echo $ind  #结果为4

3.3. 获取子串长度

语法expr match “$string” substr

例子:

var1="quickstart is a app"
sub_len= 'expr match "$var1" app'
echo $sub_len  #结果为0

sub_len='expr match "$var1" quic'
echo $sub_len  #结果为4

sub_len='expr match "$var1" quic.*'
echo $sub_len  #结果为19

3.4. 抽取字符串中的子串

方法语法说明
方法一${string:position}从string中的position开始
方法二${string:position:length}从position开始,匹配长度为length
方法三${string: -position}从右边开始匹配
方法四${string:(position)}从左边开始匹配
方法五expr substr $string $position $length从position开始,匹配长度为length

例子:

var1="kafka hadoop yarn mapreduce"
#方法一
substr_1=${var1:10}
echo $substr_1  #结果为op yarn mapreduce

#方法二
substr_2=${var1:10:5}
echo $substr_2  #结果为op ya

#方法三
substr_3=${var1: -5}
encho $substr_3  #结果为educe
substr_4=${var1:(-5)}
echo $substr_4  #结果为educe

substr_3=${var1: -5:2}
echo $substr_3  #结果为ed

#方法五
substr_5='expr substr "$var1" 10 5'
echo $substr_5  #结果为oop y

【注】:使用expr,索引计数是从1开始计算;使用${string:position},索引计数是从0开始计数。

4. 练习

需求描述:
变量string=“Bigdata process framework is Hadoop, Hadoop is an open source project” 执行脚本之后,打印输出string字符串变量,并给出用户以下选项:

  1. 打印string长度;
  2. 删除字符串中所有的Hadoop;
  3. 替换第一个Hadoop为Mapreduce;
  4. 替换全部Hadoop为Mapreduce;

用户输入数字1|2|3|4,可以执行对应项的功能;输入q|Q则退出交互模式。

思路分析:

  1. 将不同的功能模块划分,并编写函数;
function print_tips
function len_of_string
function del_hadoop
function rep_hadoop_mapreduce_first
function rep_hadoop_mapreduce_all
  1. 实现第一步所定义的功能函数
function print_tips
{
    echo "******************************"
    echo "1. 打印string长度"
    echo "2. 删除字符串中所有的Hadoop"
    echo "3. 替换第一个Hadoop为Mapreduce"
    echo "4. 替换全部Hadoop为Mapreduce"
    echo "******************************"
}


function len_of_string
{
    echo "${#string}"
}

function del_hadoop
{
    echo "${string//Hadoop/}"
}

function rep_hadoop_mapreduce_first
{
    echo "${string/Hadoop/Mapreduce}"
}

function rep_hadoop_mapreduce_all
{
    echo "${string//Hadoop/Mapreduce}"
}

  1. 程序主流程的设计
cd lesson/
cd 2.3
ll
vim example.sh

#############脚本文件内容##############
#!/bin/bash
#


string="Bigdata process framework is Hadoop, Hadoop is an open source project"

function print_tips
{
    echo "******************************"
    echo "1. 打印string长度"
    echo "2. 删除字符串中所有的Hadoop"
    echo "3. 替换第一个Hadoop为Mapreduce"
    echo "4. 替换全部Hadoop为Mapreduce"
    echo "******************************"
}


function len_of_string
{
    echo "${#string}"
}

function del_hadoop
{
    echo "${string//Hadoop/}"
}

function rep_hadoop_mapreduce_first
{
    echo "${string/Hadoop/Mapreduce}"
}

function rep_hadoop_mapreduce_all
{
    echo "${string//Hadoop/Mapreduce}"
}

while true
do
    echo "【string=$string】"
    echo
    print_tips
    read -p "Please input your choice(1|2|3|4|q|Q):" choice

    case $choice in
            1)
                    len_of_string
                    ;;
            2)
                    del_hadoop
                    ;;
            3)
                    rep_hadoop_mapreduce_first
                    ;;
            4)
                    rep_hadoop_mapreduce_all
                    ;;
            q|Q)
                    exit
                    ;;
            *)
                    echo "Error,input only in {1|2|3|4|q|Q}"
                    ;;
    esac
done

5. 命令替换

方法语法格式
方法一command
方法二$(command)

例子1:

获取系统的所有用户并输出

cat /etc/passwd | cut -d ":" -f 1
vim example_1.sh

##############脚本文件内容#################

#!/bin/bash
#

index=1

for user in `cat /etc/passwd | cut -d ":" -f 1`
do
    echo "This is $index user: $user"
    index=$(($index + 1))
done

例子2:

根据系统时间计算今年或明年

date
date +%Y  #结果为当前系统时间的年份

#或者
echo "This is $(date +%Y) year"  #结果为This is 2020 year

echo "This is $(($(date +%Y) + 1)) year"  #结果为This is 2021 year

例子3:
根据系统时间获取今年还剩下多少星期,已经过了多少星期

vim example_2.sh

###########脚本文件内容#############

#!/bin/bash
#

echo "This year have passed $(date +%j) days"
echo "This year have passed $(($(date +%j)/7)) weeks"

echo "There is $((365 - $(date +%j))) days before new year"
echo "There is $(((365 - $(date +%j))/7)) weeks before new year" 
###########脚本文件内容#############

#执行脚本
sh example_2.sh

例子4:
判定nginx进程是否存在,若不存在则自动拉起该进程

vim example_3.sh
###########脚本文件内容#############

#!/bin/bash
#

nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)

if [ $nginx_process_num -eq 0];then
    systemctl start nginx
fi

总结:

  • 和$()两者是等价的,但推荐初学者使用$(),易于掌握;缺点是极少数UNIX可能不支持,但都是支持的;
  • ( ( ) ) 主 要 用 来 进 行 整 数 运 算 , 包 括 加 减 乘 除 , 引 用 变 量 前 面 可 以 加 (())主要用来进行整数运算,包括加减乘除,引用变量前面可以加 (()),也可以不加$
$(( (100 + 30) /13 ))

num1=20;num2=30
((num++));
((num--))
$(($num1+$num2*2))

6. 有类型变量

6.1. declare 和 typeset 命令

  • declare 命令和 typeset 命令两者等价;
  • declare、typeset 命令都是用来定义变量类型的;

6.2. declare 命令参数表

参数含义
-r将变量设为只读
-i将变量设为整数
-a将变量定义为数组
-f显示此脚本前定义过的所有函数及内容
-F仅显示此脚本前定义过的函数名
-x将变量声明为环境变量
  1. declare -r #声明变量为只读类型
var2="hello python"
declare -r var2
var2="world"  #-bash: var:readonly variable
  1. declare -i #声明变量类型为整型
num1=10
num2=$num1+20
echo $num2  #结果为10+20

expr $num1 + 10  #结果为20

declare -i num3
num3=$num1+90
echo $num3  #结果为100
  1. declare -f #在脚本中显示定义的函数和内容;
  2. declare -F #在脚本中显示定义的函数
  3. declare -a
declare -a array
array=("jones" "mike" "kobe" "jordan")
echo ${array[@]}  #结果为jones mike kobe jordan
echo ${array[0]}  #结果为jones
echo ${array[1]}  #结果为mike
echo ${#array[@]} #结果为4
echo ${#array[0]} #结果为5
echo ${#array[1]} #结果为4

#输出数组内容:
echo ${array[@]}  #输出全部内容
echo ${array[1]}  #输出下标索引为1的内容

#获取数组长度:
echo ${#array}     #数组元素个数
echo ${#array[2]}  #数组内下标索引为2的元素长度

#给数组某个下标赋值:
array[0]="lily"  #给数组下标索引为1的元素赋值为lily
array[20]="hanmeimei"  #在数组尾部添加一个新元素

#删除元素:
unset array[2]  #清除元素
unset array     #清空整个数组

#分片访问:
${array[@]:1:4}  #显示数组下标索引从1开始到3的3个元素,

#内容替换
${array[@]/an/AN}  #将数组中所有元素内包含kobe的子串替换为mcg

#数组遍历
for v in ${array[@]}
do
    echo $v
done
  1. declare -x #声明为环境变量,可以在脚本中直接使用
num5=30
echo $num5  #结果为30

vim test1.sh
###############脚本文件内容#################

#!/bin/bash
#

echo $num5
###############脚本文件内容#################
sh test1.sh  #结果为""

declare -x num5
sh test1.sh  #结果为30
  • 取消声明的变量:
    • declare +r
    • declare +i
    • declare +a
    • declare +X

7. Bash数学运算之expr

方法语法
方法一expr $num1 operator $num2
方法二 ( ( (( ((num1 operator $num2))

expr操作符对照表

操作符含义
num1|num2num1不为空且非0,返回num1;否则返回num2
num1 & num2num1不为空且非0,返回num1;否则返回0
num1 < num2num1小于num2,返回1;否则返回0
num1 <= num2num1小于等于num2,返回1;否则返回0
num1 = num2num1等于num2,返回1;否则返回0
num1 != num2num1不等于num2,返回1;否则返回0
num1 > num2num1大于num2,返回1;否则返回0
num1 >= num2num1大于等于num2,返回1;否则返回0
num1 + num2求和
num1 - num2求差
num1 * num2求积
num1 / num2求商
num1 % num2求余

bash数学运算只expr:

num1=30
num2=50
expr $num1 \> $num2  #结果为0
expr $num1 \< $num2  #结果为1

expr $num1 \| $num2
expr $num1 \& $num2
expr $num1 \>= $num2
expr $num1 \<= $num2
expr $num1 = $num2
expr $num1 != $num2
expr $num1 + $num2
expr $num1 - $num2
expr $num1 \* $num2
expr $num1 / $num2
expr $num1 % $num2

num1=17
num2=5
expr $num1 / $num2  #结果为3
num3=$(($num1+num2))
echo $num3  #结果为22
num3=$(($num1*$num2))  #该方法最好不要用来比较变量之间的大小,判断相等的时候会出现问题
echo $num3  #结果为85

练习例子:
提示用户输入一个正整数num,然后计算1+2+3+…+num的值;必须对num是否为正整数做判断,不符合应当允许再次输入。

#判断变量是否为正整数

vim sum.sh

#############脚本文件内容###############

#!/bin/bash
#

while true
do
    read -p "please input a positive number: " num
    
    expr $num + 1 &> /dev/null
    
    if [ $? -eq 0 ];then
        if [ `expr $num \> 0` -eq 1 ];then
            for((i=1;i<=$num;i++))
            do
                sum=`expr $sum + $i`
            done
            echo "1+2+3+...+$num = $sum"
            exit
        fi
    fi
    echo "error,input unlegal"
    continue
done

8. Bash数学运算之bc

8.1. bc介绍

  • bc是bash内建的运算器,支持浮点数运算;
  • 内建变量scale可以设置,默认为0(不保留小数);

8.2. bc操作符对照表

操作符含义
num1 + num2求和
num1 - num2求差
num1 * num2求积
num1 / num2求商
num1 % num2求余
num1 ^ num2指数运算
which bc  #结果为/usr/bin/bc
bc        #显示bc版本号,版权等相关信息,然后就可以开始运算了
23 + 5  #结果为28
23 / 5  #结果为4

scale=2 #保留两位小数
23 / 5  #结果为4.60

#脚本中使用bc
echo "23+35" | bc  #结果为58
echo "23.3+35" | bc  #结果为58.3
echo "scale=4;23.3/3.5" | bc  #结果为6.6571

vim bc.sh
#######脚本文件内容#########

#!/bin/bash
#

read -p "num1: " num1
read -p "num2: " num2

num3=`echo "scale=4;$num1*$num2" | bc`

echo "$num1 / $num2 = $num3"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值