当前位置 博文首页 > Shell编程之变量的高级用法详解

    Shell编程之变量的高级用法详解

    作者:带翅膀的猫 时间:2021-05-29 17:49

    变量替换

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

    示例

    var1="hello world hello world"
    # 所谓最长和最短其实就是正则表达式中的贪婪模式和非贪婪模式
    
    # 删除匹配规则为*lo的数据(开头最短删除)
    echo ${var1#*lo}
    -> world hello world
    
    # 删除匹配规则为*lo的数据(开头最长删除)
    echo ${var1##*lo}
    -> world
    
    # 删除匹配规则为hel*的数据(尾部最短删除)
    echo ${var1%hel*}
    ->hello world 
    
    # 删除匹配规则为hel*的数据(尾部最长删除)
    echo ${var1%%hel*}
    ->
    
    # 替换第一个旧字符串world为Beijing
    echo ${var1/world/Beijing}
    ->hello Beijing hello world
    
    # 替换第一个旧字符串world为Beijing
    echo ${var1/world/Beijing}
    ->hello Beijing hello Beijing
    
    

    变量测试

    变量置换方式 变量y没有设置 变量y为空值 变量y设置值
    x=${y-新值} x=新值 x为空 x=$y
    x=${y:-新值} x=新值 x新值 x=$y
    x=${y+新值} x为空 x=新值 x=新值
    x=${y:+新值} x为空 x为空 x=新值
    x=${y=新值} x=新值 x为空 x=$y
    y=新值 y值不变 y值不变
    x=${y:=新值} x=新值 x=新值 x=$y
    y=新值 y=新值 y值不变
    x=${y?新值} 新值输出到标准错误输出(屏幕) x为空 x=$y
    x=${y:?新值} 新值输出到标准错误输出 新值输出到标准错误输出 x=$y

    • 如果大括号内没有":",则变量 y 为空或没有被设置,处理方法是不同的;如果大括号内有":",则变量 y
    • 不论是为空,还是没有被设置,处理方法是一样的;
    • 如果大括号内是"-“或”+",则在改变变量 x 的值的时候,变量 y 的值是不改变的;
    • 如果大括号内是"=",则在改变变量 x 的值的同时,变量 y 的值也会改变;
    • 如果大括号内是"?",则当变量 y 不存在或为空时,会把"新值"当成报错输出到屏幕上。

    示例

    # x=${y-新值}
    echo ${y=$var1}
    ->hello world hello world
    
    y=
    echo ${y-$var1}
    ->
    
    y=hello Beijing
    echo ${y-$var1}
    ->hello Beijing
    
    # x=${y:-新值}
    echo ${y:-$var1}
    ->hello world hello world
    
    y=
    echo ${y:-$var1}
    ->hello world hello world
    
    y=hello Beijing
    echo ${y:-$var1}
    ->hello Beijing
    
    # x=${y+新值}
    echo ${y+$var1}
    ->
    
    y=
    echo ${y+$var1}
    ->hello world hello world
    
    y=hello Beijing
    echo ${y+var1}
    ->hello world hello world
    
    # x=${y:+新值}
    echo ${y:+$var1}
    ->
    
    y=
    echo ${y:+$var1}
    ->
    
    y=hello Beijing
    echo ${y:+var1}
    ->hello world hello world
    
    # x=${y=新值}
    x=${y=$var1}
    echo $x
    ->hello world hello world
    echo $y
    ->hello world hello world
    
    y=
    x=${y=$var1}
    echo $x
    ->
    echo $y
    ->
    
    y=hello Beijing
    x=${y=$var1}
    echo $x
    ->hello world hello world
    echo $y
    ->hello Beijing
    
    # x=${y:=新值}
    x=${y:=$var1}
    echo $x
    ->hello world hello world
    echo $y
    ->hello world hello world
    
    y=
    x=${y:=$var1}
    echo $x
    ->hello world hello world
    echo $y
    ->hello world hello world
    
    y=hello Beijing
    x=${y:=$var1}
    echo $x
    ->hello Beijing
    echo $y
    ->hello Beijing
    
    # x=${y?新值}
    echo ${y?$var1}
    ->-bash: y: hello world hello world
    
    y=
    echo ${y?$var1}
    ->
    
    y=hello Beijing
    echo ${y?$var1}
    ->hello Beijing
    
    # x=${y:?新值}
    echo ${y?$var1}
    ->-bash: y: hello world hello world
    
    y=
    echo ${y:?$var1}
    ->-bash: y: hello world hello world
    
    y=hello Beijing
    echo ${y:?$var1}
    ->hello Beijing
    
    

     看完了我还是记不住!!参考上表吧!

    字符串处理

    字符串长度

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

    示例

    # 方法一
    var1="hello world"
    echo ${#var1}
    ->11
    
    # 方法二
    len=`expr length "$var1"`
    echo $len
    ->11
    
    ## var1有空格,必须加双引号,否则报错
    expr: syntax error
    
    ## var2没有空格,可以不需要加双引号
    var2=hello
    expr length $var2
    5
    
    

    子串字符索引

    语法 expr index $string $substring string/substring有空格,则必须加双引号 此方法并不是查找子串的索引位置,它会把子串进行字符拆分,哪个字符最先找到了则返回其索引位置。并且索引从1开始

    expr index "$var1" llo
    ->3
    
    expr index "$var1" lole
    ->2
    

    子串长度

    语法 expr match $string substring string/substring有空格,则必须加双引号

    expr match "$var1" hel
    ->3
    
    expr match "$var1" llo
    ->0
    

    expr match $string substring获取子串长度必须是从头开始匹配

    抽取子串

    语法 说明
    方法一 ${string:position} 从string中的position开始抽取子串
    方法二 ${string:position:length} 从string中的position开始,抽取长度为length的子串
    方法三 ${string: -position} (注意-position前有个空格)从尾部开始的position抽取子串
    方法四 ${string:(position)} 从string中的头部开始的position抽取子串
    方法五 expr substr $string $position $length 从string中的position开始,抽取长度为length的子串

    示例

    # 方法一
    echo ${var1:2}
    ->llo world
    
    # 方法二
    echo ${var1:2:5}
    ->llo w
    
    # 方法三
    echo ${var1: -2}
    ->ld
    
    echo ${var1: -2:1}
    ->l
    
    # 方法四
    echo ${var1:(3)}
    ->lo world
    
    echo ${var1:(3):2}
    ->lo
    
    echo ${var1:(-2):1}
    ->l
    
    # 方法五
    expr substr "$var1" 2 5
    ->ello

    注意:expr substr $string $position $length的position从1开始,而${string:position:length}的从0开始。

    var2=hello
    echo ${var2:2:5}
    ->llo
    
    expr substr $var2 2 5
    ->ello
    
    

    小试牛刀

          需求描述:变量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则退出交互模式。

    #!/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 "q|Q->退出"
     echo "=============================="
    }
    
    function len_of_string
    {
     echo "${#string}"
    }
    
    function del_hadoop
    {
     echo "${string//Hadoop/}"
    }
    
    function rep_first_hadoop_mapreduce
    {
     echo "${string/Hadoop/Mapreduce}"
    }
    
    function rep_all_hadoop_mapreduce
    {
     echo "${string//Hadoop/Mapreduce}"
    }
    while true
    do
     echo ""
            echo ""
            echo ""
            echo ""
     echo "【string=$string】"
     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_first_hadoop_mapreduce;;
      4)rep_all_hadoop_mapreduce;;
      q|Q)exit;;
      *)echo "Error input,only in (1|2|3|4|q|Q)";;
     esac
    done

    命令替换

          Shell 命令替换是指将命令的输出结果赋值给某个变量。比如,在某个目录中输入 ls 命令可查看当前目录中所有的文件,但如何将输出内容存入某个变量中呢?这就需要使用命令替换了,这也是 Shell 编程中使用非常频繁的功能。

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

    示例

    # 获取系统的所有用户并输出
    #!/bin/bash
    
    index=1
    for user in `cat /etc/passwd | cut -d ":" -f 1`
    do
     echo "这是第 $index 个用户,名称为:$user"
     index=$(($index + 1))
            # $(())主要用来进行整数运算,引用变量前面可以加$也可以不加
    done
    
    # 根据系统时间计算今年或明年
    #!/bin/bash
    
    year=`date +%Y`
    echo "今年是$year年,明年是$(($year+1))年"
    
    # 根据系统时间获取今年还剩下多少星期,已经过了多少星期
    #!/bin/bash
    
    # 计算现在是今年第几天
    #!/bin/bash
    
    days=$(date +%j)
    weeks=$((days/7))
    remain_weeks=$((52-weeks))
    echo "今年还剩$remain_weeks个星期,已经过了$weeks个星期"
    
    # 判定nginx进程是否存在,若不存在则自动拉起进程
    #!/bin/bash
    
    nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)
    if [ $nginx_process_num -eq 0 ];then
     echo "nginx未启动,拉起中..."
     systemctl start nginx
    else
     echo "nginx已启动..."
    fi
    
    

    有类型变量

          在之前的变量声明中都是没有指定变量类型的,在Shell编程中如果需要为变量指定类型则需要使用declare和typeset命令。这两个命令是等价的。(下表中-号为添加,取消则使用+号,如+x)

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

    示例

    # 设置为只读
    var1="hello wordl"
    var1="hello shell"
    declare -r var1
    var1="hello java"
    ->-bash: var1: readonly variable
    
    # 设置为整形
    num1=20
    num2=$num1+30
    echo $num2
    ->20+30 #linux默认设置为字符串
    declare -i num3
    num3=$num1+30
    echo $num3
    ->50
    
    # 定义数组
    declare -a array
    array=(1 2 3 4)
    # 输出全部内容
    echo ${array[@]} 
    # 输出下标索引为1的内容
    echo ${array[1]}
    # 数组内元素个数
    echo ${#array[@]}
    # 指定索引赋值
    array[0]=555
    # 尾部添加元素
    array[4]=666
    # 删除元素
    # 删除索引为2的元素
    unset array[2]
    # 清空整个数组
    unset array
    # 分片访问
    # 显示数组下标索引从1开始到3的三个元素(包头不包尾)
    ${array[@]:1:4}
    # 数组遍历
    for n in ${array[@]}
    do
        echo $n
    done
    
    # 显示脚本前定义过的所有函数及内容
    # 在前问小试牛刀的print_tips方法后添加declare -f,即可发现只显示了命令前的函数及内容
    
    

    数学运算之expr

    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 $num1 \| $num2,expr $num1 \> $num2,否则报错。

    num1=20
    num2=100
    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
    expr $num1 / $num2
    expr $num1 % $num2
    

    数学运算之bc

          bc是bash内建的运算器,支持浮点数运算。默认情况下bc运算精确到整数,可以设置scale来保留指定位数的小数。

    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
    4
    scale=2
    23/5
    4.60
    

         在shell中通常通过管道来使用bc。如:echo "2.5/3.65" | bc或echo 'scale=2; (2.777 - 1.4744)/1' | bc。注意:后者的/1操作,如果不进行除法则无法保留指定位数的小数
          bc 除了 scale 来设定小数位之外,还有 ibase(输入数据的进制) 和 obase(输出的数据进制) 来其它进制的运算。

    echo "ibase=2;111" |bc
    ->7
    
    echo "obase=2;192" |bc
    ->11000000
    
    
    
    js
    下一篇:没有了