zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Shell 编程(一):Shell 变量的高级用法

编程变量shell 用法 高级
2023-06-13 09:16:58 时间

变量替换

语法

说明

${变量名#匹配规则}

从变量开头进行规则匹配,将符合最短的数据删除

${变量名##匹配规则}

从变量开头进行规则匹配,将符合最长的数据删除

${变量名%匹配规则}

从变量尾部进行规则匹配,将符合最短的数据删除

${变量名%%匹配规则}

从变量尾部进行规则匹配,将符合最长的数据删除

${变量名/旧字符串/新字符串}

变量内容符合旧字符串则,则第一个旧字符串会被新字符串取代

${变量名//旧字符串/新字符串}

变量内容符合旧字符串则,则全部的旧字符串会被新字符串取代

例子

#!/bin/bash
# var1 = I love you,Do you love me
var1="I love you,Do you love me";
echo "var1 = ${var1}";

# ${变量名#匹配规则} var2 = e you,Do you love me
var2=${var1#*ov}
echo "var2 = ${var2}";

# ${变量名##匹配规则} var3 = e me
var3=${var1##*ov}
echo "var3 = ${var3}";

# ${变量名%匹配规则} var4 = I love you,Do you l
var4=${var1%ov*}
echo "var4 = ${var4}";

# ${变量名%%匹配规则} var5 = I l
var5=${var1%%ov*}
echo "var5 = ${var5}";

# ${变量名/旧字符串/新字符串} var6 = I like you,Do you love me
var6=${var1/love/like}
echo "var6 = ${var6}";

# ${变量名//旧字符串/新字符串} var7 = I like you,Do you like me
var7=${var1//love/like}
echo "var7 = ${var7}";

变量测试

变量配置方式

Str没有配置

Str为空字符串

Str已配置且非空

var=${str-expr}

var=expr

var=

var=$str

var=${str:-expr}

var=expr

var=expr

var=$str

var=${str+expr}

var=

var=expr

var=expr

var=${str:+expr}

var=

var=

var=expr

var=${str=expr}

var=expr

var

var=$str

var={str:=expr}

var=expr

var=expr

var=$str

字符串处理

计算字符串长度

语法

说明

方法一

${#string}

方法二

expr length “$string”

string 有空格,则必须加双引号

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

语法

说明

expr index $string $substring

抽取子串

语法

说明

方法一

${string:position}

从 string 中的 position 开始

方法二

${stringlength}

从 position 开始,匹配长度为 length

方法三

${string: -position}

从右边开始匹配

方法四

${string:(position)}

从左边开始匹配

方法五

expr substr $string $position $length

从 position 开始,匹配长度为 length

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

例子

  1. 获取字符串长度
  2. 通过expr获取字符串长度
  3. 获取字符索引位置
  4. 获取子串长度
  5. 抽取字符串中的子串
  6. 索引抽取字符串中的子串
#!/bin/bash
# 获取字符串长度
var1="Hello World"
echo "var1 = $var1"

len=${#var1}
echo "var1 len = $len"

# 通过expr获取
len=`expr length "$var1"`
echo "var1 len = $len"

# 获取字符索引位置
index=`expr index "$var1" rld`
echo "rld index = $index"

index=`expr index "$var1" a1d`
echo "a1d index = $index"

#获取子串长度(tips:匹配规则是从头开始匹配中间匹配无效)
sub_len=`expr match "$var1" rld`
echo "rld sub_len = $sub_len"

# 从 Hello 开始匹配则可成功
sub_len=`expr match "$var1" Hello`
echo "Hello sub_len = $sub_len"

# 抽取字符串中的子串
var2="redis mysql pgsql sqlserver"
echo "var2 = $var2"

# 从 var2 第 10 位开始提取子串
substr1=${var2:10}
echo "substr1 = $substr1"

# 从 var2 第 10 位开始提取长度为 5 的子串
substr2=${var2:10:5}
echo "substr2 = $substr2"

# 从 var2 的右边第 5 开始提取子串
substr3=${var2:-5}
echo "substr3 = $substr3"

substr4=${var2:(-5)}
echo "substr4 = $substr4"

# 从 var2 的右边第 5 开始提取长度为 5 的子串
substr5=${var2:-5:5}
echo "substr5 = $substr5"

# 从 5 开始,匹配长度为 10(tips:使用expr,索引计数是从1开始计算;使用${string:position}, 索引计数是从0开)
substr6=`expr substr "$var2" 5 10`
echo "substr6 = $substr6"

输出

var1 = Hello World
var1 len = 11
var1 len = 11
rld index = 3
a1d index = 11
rld sub_len = 0
Hello sub_len = 5
var2 = redis mysql pgsql sqlserver
substr1 = l pgsql sqlserver
substr2 = l pgs
substr3 = redis mysql pgsql sqlserver
substr4 = erver
substr5 = redis mysql pgsql sqlserver
substr6 = s mysql pg

练习

字符串处理脚本

需求描述

变量 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. 将不同的功能模块划分,并编写函数
  2. 实现第一步所定义的功能函数
  3. 程序主流程设置

代码

#!/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 "-----------------------------"
}

# 打印 string 长度
function len_of_string {
  echo ${#string}
}

# 删除字符串中所有的 Hadoop
function del_hadoop {
  echo ${string//Hadoop/}
}

# 替换第一个 Hadoop 为 Mapreduce
function rep_hadoop_mapreduce_first {
  echo ${string/Hadoop/mapreduce}
}

# 替换全部 Hadoop 为 Mapreduce
function rep_hadoop_mapreduce_all {
  echo ${string//Hadoop/mapreduce}
}

# 主程序
while true; do
  echo "[string=$string]"
  print_tips
  read -p "Pls input you 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
  echo "-----------------------------"
done

命令替换

方法

语法格式

方法一

`command`

方法二

$(command)

`` 和()两者是等价的,但推荐初学者使用(),易于掌握;缺点是极少数UNIX可能不支持

(())主要用来进行整数运算,包括加减乘除,引用变量前面可以加,也可以不加

例子

  1. 获取系统所有用户并输出
  2. 根据系统时间计算今年或明年
  3. 根据系统时间获取今年还剩下多少星期,已经过了多少星期
  4. 判断 nginx 进程是否存在,若不存在则自动拉起该进程

1).获取系统所有用户并输出

#!/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

输出

This is 1 user: root
This is 2 user: bin
This is 3 user: daemon
This is 4 user: adm
This is 5 user: lp
This is 6 user: sync
This is 7 user: shutdown
This is 8 user: halt
This is 9 user: mail
This is 10 user: operator
This is 11 user: games
This is 12 user: ftp
This is 13 user: nobody
This is 14 user: systemd-network
This is 15 user: dbus
This is 16 user: polkitd
This is 17 user: sshd
This is 18 user: postfix
This is 19 user: chrony
This is 20 user: nscd
This is 21 user: tcpdump
This is 22 user: ntp
This is 23 user: www
This is 24 user: redis
This is 25 user: openvpn
This is 26 user: emqx
This is 27 user: epmd

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

#!/bin/bash
echo "This is $(date +%Y) year";
echo "This is $(($(date +%Y)+1)) year";

输出

This is 2022 year
This is 2023 year

2).根据系统时间获取今年还剩下多少星期,已经过了多少星期

# example.sh
echo "This year have passed $(date +%j) days";
echo "This year have passed $(date +%V) weeks";
echo "There is $((365-$(date +%j))) days before new year";
echo "There is $(((365-$(date +%j))/7)) weeks before new year";

输出

This year have passed 363 days
This year have passed 52 weeks
There is 2 days before new year
There is 0 weeks before new year

4).判断 nginx 进程是否存在,若不存在则自动拉起该进程

#!/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

有类型变量

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

declare命令参数表

参数

含义

-r

将变量设为只读

-i

将变量设为整数

-a

将变量定义为数组

-f

显示此脚本前定义过的所有函数及内容

-F

仅显示此脚本前定义过的函数名

-x

将变量声明为环境变量

取消声明的变量:declare +r;declare +i;declare +a;declare +f;declare +F;declare +x;

例子

  1. 声明变量为只读类型
  2. 声明变量类型为整型
  3. 在脚本中显示定义的函数和内容
  4. 在脚本中显示定义的函数
  5. 将变量声明为环境变量
  6. 声明变量为数组

1).声明变量为只读类型

# example.sh
string="Hello world";
declare -r string
echo "string = $string"

# 再次赋值将无法修改
string="zxcvadsf"
echo "string = $string"

输出

string = Hello world
example7.sh: line 7: string: readonly variable
string = Hello world

2).声明变量类型为整型

# example.sh
num1=100
num2=10
num3=$num1+$num2
echo $num3

declare -i num3
num3=$num1+$num2
echo "num3 = $num3"

输出

num3 = 100+10
num3 = 110

3).在脚本中显示定义的函数和内容 && 在脚本中显示定义的函数

declare -f
declare -F

5).将变量声明为环境变量

# example7.sh
echo $num4

# bash
> declare -x num4=122

# example7.sh
echo $num4

输出

#第一行为空
122

6).声明变量为数组

# example.sh
declare -a array
array=("jones" "mike" "kobe" "jordan")
echo "array = ${array[@]}"
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
echo "array length = ${#array[@]}"

for v in ${array[@]}
do
    echo $v
done

输出

array = jones mike kobe jordan 
array[0] = jones
array[1] = mike
array length = 4
jones
mike
kobe
jordan

Bash 数学运算之 expr

语法格式

方法

语法

方法一

expr $num1 operator $num2

方法二

$(($num1 operator $num2 ))

expr 操作符对照表

操作符

含义

num1 | num2

num1不为空且非0 ,返回num1 ;否则返回num2

num1 & num2

num1不为空且非0,返回num1 ;否则返回0

num1 < num2

num1小于num2 ,返回1 ;否则返回0

num1 <= num2

num1小于等于num2,返回1 ;否则返回0

num1 = num2

num1等于num2 ,返回1 ;否则返回0

num1 != num2

num1不等于num2,返回1 ;否则返回0

num1 > num2

num1大于num2 ,返回1 ;否则返回0

num1 >= num2

num1大于等于num2,返回1 ;否则返回0

使用 expr 命令时,表达式中的运算符左右必须包含空格,如果不包含空格,将会输出表达式本身:

例子

练习

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

思路

  1. 通过 expr 操作可判断是否是整数(只有整数才能使用expr)
  2. 再进行查看操作数是否大 0
# example.sh
#!/bin/bash
while true
do
  read -p "pls 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 enlegal"
  continue
done

输出

> sh example9.sh 
pls input a positive number :10
1+2+3...+10 = 55

Bash 数学运算之 bc

  • bc 是 bash 内建的运算器,支持浮点数运算
  • 内建变量 scale 可以设置,默认为 0

bc操作符对照表

操作符

含义

num1 + num2

求和

num1 - num2

求差

num1 * num2

求积

num1 / num2

求商

num1 % num2

求余

num1 ^ num2

指数运算

> bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 

scale=4
23.444/5.2
4.5084
3.56+35.4
38.96