变量替换

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

变量替换练习

删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@localhost ~]# variable_1="I love you.Do you love me"
[root@localhost ~]# echo $variable_1
I love you.Do you love me
[root@localhost ~]# var1=${variable_1#*ov}
[root@localhost ~]# echo $var1
e you.Do you love me
[root@localhost ~]# var2=${variable_1##*ov}
[root@localhost ~]# echo $var2
e me
[root@localhost ~]# var3=${variable_1%ov*}
[root@localhost ~]# echo $var3
I love you.Do you l
[root@localhost ~]# var4=${variable_1%%ov*}
[root@localhost ~]# echo $var4
I l

替换

1
2
3
4
5
6
7
8
[root@localhost ~]# echo $PATH
/usr/local/maven/bin:/usr/local/jdk1.8/bin:/usr/local/jdk1.8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# var5=${PATH/bin/BIN}
[root@localhost ~]# echo $var5
/usr/local/maven/BIN:/usr/local/jdk1.8/bin:/usr/local/jdk1.8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# var6=${PATH//bin/BIN}
[root@localhost ~]# echo $var6
/usr/local/maven/BIN:/usr/local/jdk1.8/BIN:/usr/local/jdk1.8/BIN:/usr/local/sBIN:/usr/local/BIN:/usr/sBIN:/usr/BIN:/root/BIN

变量测试(了解)

变量配置方式 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=$str 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
  • 将子拆分成字符,一个一个字符中查找

计算子串长度

  • 语法:expr match $string substr

抽取子串

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

字符串练习

1. 计算字符串长度

1
2
3
4
5
6
7
[root@localhost ~]# var1="Hello World"
[root@localhost ~]# len=${#var1}
[root@localhost ~]# echo $len
11
[root@localhost ~]# lens=`expr length "$var1"`
[root@localhost ~]# echo $lens
11

2. 获取字符索引位置

1
2
3
4
5
6
7
[root@localhost ~]# var2="quickstart is app"
[root@localhost ~]# ind=`expr index "$var2" start` # 获取start索引位置,从头1开始
[root@localhost ~]# echo $ind
6
[root@localhost ~]# ind=`expr index "$var2" uniq` # 是将字符拆分单个字符,根据单个字符查找,指导找到对应的字符的位置
[root@localhost ~]# echo $ind
1

3.获取子串长度

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# var3="quickstart is app"
[root@localhost ~]# sub_len=`expr match "$var3" app`
[root@localhost ~]# echo $sub_len
0
[root@localhost ~]# sub_len=`expr match "$var3" quick` # 必须从头开始比配,如果从中间开始则匹配不到
[root@localhost ~]# echo $sub_len
5
[root@localhost ~]# sub_len=`expr match "$var3" quick.*`
[root@localhost ~]# echo $sub_len
17

4.抽取字符串中的子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost ~]# var4="kafka hadoop yarn mapreduce"
[root@localhost ~]# substr1=${var4:10} # 索引是从0开始
[root@localhost ~]# echo $substr1
op yarn mapreduce
[root@localhost ~]# substr2=${var4:10:5}
[root@localhost ~]# echo $substr2
op ya
[root@localhost ~]# substr3=${var4: -5} # 注意空格
[root@localhost ~]# echo $substr3
educe
[root@localhost ~]# substr4=${var4:(-5)} # 加括号则不需要空格
[root@localhost ~]# echo $substr4
educe
[root@localhost ~]# substr5=${var: -5:2}
[root@localhost ~]# echo $substr5
ed
[root@localhost ~]# substr6=`expr substr "$var4" 10 5`
[root@localhost ~]# echo $substr6
oop y

注意:

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

综合实战:字符串处理完整脚本

需求描述:

  • 变量:string=”Bigdata process framework is Hadoop,Hadoop is an open source project”

  • 执行脚本后,打印输出string字符串变量,并给出用户以下选项:

    • 打印string长度
    • 删除字符串中所有的Hadoop
    • 替换第一个Hadoop为Mapreduce
    • 替换全本Hadoop为Mapreduce
  • 用户输入数字1|2|3|4,可以执行对应项的功能,输入q|Q则退出交互模式

  • 思路分析:

    • 将不同的功能模块划分,并编写函数
      • function print_tips
      • function len_of_string
      • function del_hadoop
      • function rep_hadoop_mapreduce_first
      • function rep_hadoop_mapreduce_all
    • 实现上一步所定义的功能函数
    • 程序主流程的设计

脚本如下(注意:该脚本在CentOS下执行OK,Ubuntu下执行语法错误)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/bin/bash

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

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 "Pls 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

命令替换

语法格式

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

练习

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

    1
    2
    3
    4
    5
    6
    7
    8
    #!/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
  1. 根据系统时间计算今年或明年

    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash

    # 获取今年的年份
    echo "This is $(date +%Y) year"

    # 明年的年份
    echo "This is $(($(date +%Y) + 1)) year"
  1. 根据系统时间获取今年还剩下多少星期,已经过了多少星期

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/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"
  1. 判定Nginx进程是否存在,若不存在则自动拉起该进程

    1
    2
    3
    4
    5
    6
    #!/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可能不支持,但``` `` ```都是支持的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

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



# 有类型变量

## declare和typeset命令

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

## declare命令参数表

| 参数 | 含义 |
| ---- | ---------------------------------- |
| -r | 将变量设为只读 |
| -i | 将变量设为整数 |
| -a | 将变量定义为数组 |
| -f | 显示此脚本前定义过的所有函数及内容 |
| -F | 仅显示此脚本前定义过的函数名 |
| -x | 将变量声明为环境变量 |

有类型变量总结:

1. declare -r #声明变量为只读类型

```shell
jingdeMacBook-Pro:~ apple$ var1="hello world"
jingdeMacBook-Pro:~ apple$ echo $var1
hello world
jingdeMacBook-Pro:~ apple$ var1="hello Beijing"
jingdeMacBook-Pro:~ apple$ echo $var1
hello Beijing
jingdeMacBook-Pro:~ apple$ declare -r var1
jingdeMacBook-Pro:~ apple$ var1="hello Shanghai"
-bash: var1: readonly variable
  1. declare -i #声明变量类型为整型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    jingdeMacBook-Pro:~ apple$ num1=10
    jingdeMacBook-Pro:~ apple$ num2=$num1+20
    jingdeMacBook-Pro:~ apple$ echo $num2
    10+20
    jingdeMacBook-Pro:~ apple$ expr $num1 + 10
    20
    jingdeMacBook-Pro:~ apple$ declare -i num3
    jingdeMacBook-Pro:~ apple$ num3=$num1+90
    jingde
  1. declare -f #在脚本中显示定义的函数和内容

  2. declare -F #在脚本中显示定义的函数

  3. declare -a

    1. 定义数组

      1
      2
      jingdeMacBook-Pro:~ apple$ declare -a array
      jingdeMacBook-Pro:~ apple$ array=("a" "b" "c" "d")
  1. 输出数组内容

    1. 输出全部内容

      1
      2
      jingdeMacBook-Pro:~ apple$ echo ${array[@]}
      a b c d
  2. 输出下标索引为1的内容(数组下标从0开始)

     
1
2
jingdeMacBook-Pro:~ apple$ echo ${array[1]}
b
  1. 获取数组长度

    1. 数组内元素个数

      1
      2
      jingdeMacBook-Pro:~ apple$ echo ${#array[@]}
      4
  2. 数组内下标索引为2的元素长度

     
1
2
jingdeMacBook-Pro:~ apple$ echo ${#array[2]}
1
  1. 给数组某个下标赋值

    1. 给数组下标索引为1的元素赋值为jack

      1
      2
      3
      jingdeMacBook-Pro:~ apple$ array[1]="jack"
      jingdeMacBook-Pro:~ apple$ echo ${array[@]}
      a jack c d
  2. 在数组尾部添加一个新元素

     
1
2
3
jingdeMacBook-Pro:~ apple$ array[5]="may"
jingdeMacBook-Pro:~ apple$ echo ${array[@]}
a jack c d may
  1. 删除元素

    1. 清空元素

      1
      2
      3
      4
      5
      jingdeMacBook-Pro:~ apple$ echo ${array[@]}
      a jack c d may
      jingdeMacBook-Pro:~ apple$ unset array[2]
      jingdeMacBook-Pro:~ apple$ echo ${array[@]}
      a jack d may
  2. 清空整个数组

     
1
2
jingdeMacBook-Pro:~ apple$ unset array
jingdeMacBook-Pro:~ apple$ echo ${array[@]}
  1. 分片访问

    1. 显示数组下标索引从1开始到3的3个元素

      1
      2
      3
      4
      jingdeMacBook-Pro:~ apple$ declare -a array
      jingdeMacBook-Pro:~ apple$ array=("a" "b" "c" "d")
      jingdeMacBook-Pro:~ apple$ echo ${array[@]:1:4}
      b c d
  2. 内容替换

    1. 将数组总所有元素内包含aa的子串替换为nb

      1
      2
      3
      4
      jingdeMacBook-Pro:~ apple$ declare -a array
      jingdeMacBook-Pro:~ apple$ array=("aaa" "b" "caa" "d")
      jingdeMacBook-Pro:~ apple$ echo ${array[@]/aa/nb}
      nba b cnb d
  1. 数组遍历

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash

    declare -a array
    array=("a" "b" "c" "d")
    for v in ${array[@]}
    do
    echo $v
    done
    1. declare -x 声明为环境变量,可以在脚本中直接使用
  1. 取消声明的变量:将减号(-)变为加号(+)

    1. declare +r
    2. declare +i
    3. declare +a
    4. declare +X

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
num1 + num2 求和
num1 - num2 求差
num1 * num2 求积
num1 / num2 求商
num1 % num2 求余

注意:

  • 符号需要加转义符号\和格式

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
jingdeMacBook-Pro:~ apple$ num1=30
jingdeMacBook-Pro:~ apple$ num2=50
jingdeMacBook-Pro:~ apple$ expr $num1 \> $num2
0
jingdeMacBook-Pro:~ apple$ expr $num1 \< $num2
1
jingdeMacBook-Pro:~ apple$ expr $num1 + $num2
80
jingdeMacBook-Pro:~ apple$ num3=`expr $num1 + $num2`
jingdeMacBook-Pro:~ apple$ echo $num3
80
jingdeMacBook-Pro:~ apple$ expr $num1 * $num2
expr: syntax error
jingdeMacBook-Pro:~ apple$ expr $num1 \* $num2 # 注意:乘号*,需要加转义
1500
jingdeMacBook-Pro:~ apple$ expr $num2 / $num1
1
jingdeMacBook-Pro:~ apple$ expr $num2 % $num1
20
jingdeMacBook-Pro:~ apple$ num3=$(($num1+$num2))
jingdeMacBook-Pro:~ apple$ echo $num3
80
jingdeMacBook-Pro:~ apple$ num3=$(($num1*$num2))
jingdeMacBook-Pro:~ apple$ echo $num3
1500
jingdeMacBook-Pro:~ apple$ num3=$(($num2/$num1))
jingdeMacBook-Pro:~ apple$ echo $num3
1
jingdeMacBook-Pro:~ apple$ num3=$(($num2%$num1))
jingdeMacBook-Pro:~ apple$ echo $num3
20
  • 练习例子:提示用户输入一个正整数num,然后1+2+3+…+num的值;必须对num是否为正整数做判断,不符合应当允许再次输入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/bin/bash
    #

    while true
    do
    read -p "pls input a positive number:" num

    ## 判断输入的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"
    contiune
    done

Bash数学运算之bc

介绍

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

bc操作符对照表

操作符 含义
num1 + num2 求和
num1 - num2 求差
num1 * num2 求积
num1 / num2 求商
num1 % num2 求余
num1 ^ num2 指数运算

注意:bc命令需要安装

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@localhost ~]# which bc
/usr/bin/bc
[root@localhost ~]# 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'.
23 + 5
28
23 - 5
18
20 / 5
4
20 % 4
0
23 / 5
4
scale=2
23 / 5
4.60
scale=6
23 / 5
4.600000

[root@localhost ~]# echo "23+35" | bc
58
[root@localhost ~]# echo "23.3+35" | bc
58.3
[root@localhost ~]# echo "scale=4;23.3/3.5" | bc
6.6571
1
2
3
4
5
6
7
8
9
#!/bin/bash
#

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

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

echo "$num1 / $num2 = $num3"