Shell(1)

变量

Bash脚本中变量可以分为字符串、数字、数组等等,较为常用的还是字符串

命名规范

  • 只包含字母、数字和下划线: **变量名可以包含字母(大小写敏感)、数字和下划线 _**,不能包含其他特殊字符。
  • 不能以数字开头: 变量名不能以数字开头,但可以包含数字。
  • 避免使用 Shell 关键字: 不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。
  • 使用大写字母表示常量: 习惯上,常量的变量名通常使用大写字母,例如 PI=3.14。
  • 避免使用特殊符号: 尽量避免在变量名中使用特殊符号,因为它们可能与 Shell 的语法产生冲突。
  • 避免使用空格: 变量名中不应该包含空格,因为空格通常用于分隔命令和参数。

定义

# 注意不能有空格
# str = "abc"是错误的写法
str="abc"
str='abc'

digit=12
declare -i digit=12

array=(1 2 3 4 5)
declare -A associate_array=(["A"]="1" ["B"]="2" ["C"]="3")

引用

str="abc"
digit=12
array=(1 2 3 4 5)
# 获得变量的值/引用变量需要使用$
# 字符串变量
echo $str
# >>> abc
echo $digit
# >>> 12
echo ${array[@]}
# >>> 1 2 3 4 5

# 对于可能有歧义的变量名字需要使用{}括起来
str="abc"
# 如果不使用{}将会把strabc识别为一个变量
echo "${str}abc"
# >>> abcabc
echo $str
# >>> abc

字符串

在Bash脚本中经常使用的一种变量,具有最主要的特征

单引号与双引号的区别

# 1.单引号中无法识别变量名
name="yangman"
str1="I love ${name}"
str2='I love ${name}'
echo $str1
# >>> I love yangman
echo $str2
# >>> I love ${name}

# 2.单引号无法使用单引号(即使转义)
str1="myname \"\'"
str2='myname \"\''

echo $str1 \'
# 显而易见,即使转义了单引号也会引起后续问题,必须只能成对出现


# 3.二者都可以使用拼接操作
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# >>> hello, runoob ! hello, runoob !

# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
# >>> hello, runoob ! hello, ${your_name} !

计算字符串长度

str="abc"
echo ${#str}
# >>> 3
echo ${#str[0]}
# >>> 3

# 注意这里虽然使用了索引
# 但是字符串实则为不可迭代/不可索引的对象!!!

字符串切片操作

str="1234567"
# string:index[:length]
echo ${str:1}
# >>> 234567
echo ${str:1:3}
# >>> 234

查找子串

echo $(expr index "string" io)
# 找到string串中第一次出现i或者o的位置

数组

数组由索引的类型分为两大类

  • 整数索引数组,顾名思义,索引都是整数的数组
  • 关联数组,索引可以是字符串也可是整数

数组定义

# 除了和一般变量定义外
# 数组支持直接通过下标赋值

# 索引数组索引不要求连续
new_array[0]="1"
new_array[1]="2"
new_array[6]="3"
new_array[10]="6"

# 关联数组需要声明
declare -A associ_array
associ_array["A"]="1"
associ_array["B"]="1"
associ_array["D"]="1"
associ_array["SD"]="1"

数组索引

  • 正常语言的索引,通过下标取值
    echo ${array[index]}

计算数组长度

# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
length=${#array_name[n]}

列出所有元素

array=(1 2 3 4 5)

# 1.列出所有的value

echo ${array[@]}
# >>> 1 2 3 4 5
# 实际表现为 "1" "2" "3" "4" "5"
echo ${array[*]}
# >>> 1 2 3 4 5
# 实际表现为 "1 2 3 4 5"

# 意味着一个是可迭代的,一个不是可迭代的
for i in ${array[@]}; do
echo $i
done
# >>> 1
# >>> 2
# >>> 3
# >>> 4
# >>> 5
for i in ${array[*]}; do
echo $i
done
# >>> 1 2 3 4 5

# 列出所有的key
# 都是可迭代的
echo ${!array[@]}
# >>> 0 1 2 3 4
echo ${!array[*]}
# >>> 0 1 2 3 4

符号

Shell类

$()

  • 将其中的字符识别为shell命令,并将结果作为返回值
    echo $(ls)
    var=$(ls)
    for i in $var;do
    echo $i
    done
    反引号
  • 同上,转义为命令并返回结果
    echo `ls`
    var=`ls`
    ()
  • 开启一个shell子进程,其内部变量不影响当前进程
    # 子 Shell
    (a=10; echo $a) # 输出 10
    echo $a # 输出空,因为子 Shell 中的变量不影响父 Shell

    # 数组
    arr=(1 2 3)
    echo ${arr[1]} # 输出 2

算术类

  • 对于整数类型或者纯数字的字符串

(())

  • 支持所有c语言支持的运算符
  • 算术拓展,在其中可以直接使用各种运算符并且不需要引用变量
    a=5
    b=10
    ((a++))
    ((c = a + b))
    echo $c
    # >>> 16
  • 支持运算符
    运算符 说明 示例
    + 加法 (( a = 5 + 3 ))
    - 减法 (( a = 5 - 3 ))
    * 乘法 (( a = 5 * 3 ))
    / 整数除法(只返回整数部分) (( a = 5 / 2 )) (结果 2
    % 取模 (( a = 5 % 2 )) (结果 1
    ** 幂运算 (( a = 2 ** 3 )) (结果 8
    ++ 自增 (( a++ ))(( ++a ))
    -- 自减 (( a-- ))(( --a ))
    = 赋值 (( a = 10 ))
    += 加法赋值 (( a += 2 ))
    -= 减法赋值 (( a -= 2 ))
    *= 乘法赋值 (( a *= 2 ))
    /= 除法赋值 (( a /= 2 ))
    %= 取模赋值 (( a %= 2 ))
    == 等于 (( a == b ))
    != 不等于 (( a != b ))
    > 大于 (( a > b ))
    < 小于 (( a < b ))
    >= 大于等于 (( a >= b ))
    <= 小于等于 (( a <= b ))
    && 逻辑与 (( a > 3 && b < 5 ))
    || 逻辑或 (( a > 3 || b < 5 ))
    ! 逻辑非 (( !a ))
    & 按位与 (( a & b ))
    | 按位或 (( a | b ))
    ^ 按位异或 (( a ^ b ))
    << 左移 (( a << 1 ))
    >> 右移 (( a >> 1 ))

$(())

  • 也是算术拓展,但是这里是返回了值,不能像上面一样内部赋值
    a=5
    b=10
    a=$((a + 1))
    c=$((a + b))
    echo $c
    # >>> 16
    $[]
  • 同上,但是已经过时,尽量补药使用

比较类

[]

  • test比较方法的简写
  • 对于数字比较(纯数字的字符串)
    • 支持==!=
    • 支持-gt-lt-eq-ne-gele
    • 支持!-o-a,不能直接支持&&||
      a=10
      b=20

      if [ $a != $b ]
      then
      echo "$a != $b : a 不等于 b"
      else
      echo "$a == $b: a 等于 b"
      fi

      # if [ $a -lt 100 ] && [ $b -gt 15 ]
      if [ $a -lt 100 -a $b -gt 15 ]
      then
      echo "$a 小于 100 且 $b 大于 15 : 返回 true"
      else
      echo "$a 小于 100 且 $b 大于 15 : 返回 false"
      fi

      if [ $a -lt 100 -o $b -gt 100 ]
      then
      echo "$a 小于 100 或 $b 大于 100 : 返回 true"
      else
      echo "$a 小于 100 或 $b 大于 100 : 返回 false"
      fi

      if [ $a -lt 5 -o $b -gt 100 ]
      then
      echo "$a 小于 5 或 $b 大于 100 : 返回 true"
      else
      echo "$a 小于 5 或 $b 大于 100 : 返回 false"
      fi
  • 对于字符串比较
    • 支持=!= !!!!!!!此处只有一个=
    • 支持-z-n$
    • 支持\>\<字符串排序
    • 需要注意比较时字符串会默认去除引号,所以保险起见需要加上引号
      a="abc"
      b="efg"

      if [ "$a" = "$b" ]
      then
      echo "$a = $b : a 等于 b"
      else
      echo "$a = $b: a 不等于 b"
      fi
      if [ "$a" != "$b" ]
      then
      echo "$a != $b : a 不等于 b"
      else
      echo "$a != $b: a 等于 b"
      fi
      if [ -z "$a" ]
      then
      echo "-z $a : 字符串长度为 0"
      else
      echo "-z $a : 字符串长度不为 0"
      fi
      if [ -n "$a" ]
      then
      echo "-n $a : 字符串长度不为 0"
      else
      echo "-n $a : 字符串长度为 0"
      fi
      if [ "$a" ]
      then
      echo "$a : 字符串存在且不为空"
      else
      echo "$a : 字符串为空/不存在"
      fi
  • 文件测试
    • -e -r -x -w
      file="/var/www/runoob/test.sh"

      if [ -r $file ]
      then
      echo "文件可读"
      else
      echo "文件不可读"
      fi

      if [ -w $file ]
      then
      echo "文件可写"
      else
      echo "文件不可写"
      fi

      if [ -x $file ]
      then
      echo "文件可执行"
      else
      echo "文件不可执行"
      fi

      if [ -f $file ]
      then
      echo "文件为普通文件"
      else
      echo "文件为特殊文件"
      fi

      if [ -d $file ]
      then
      echo "文件是个目录"
      else
      echo "文件不是个目录"
      fi

      if [ -s $file ]
      then
      echo "文件不为空"
      else
      echo "文件为空"
      fi

      if [ -e $file ]
      then
      echo "文件存在"
      else
      echo "文件不存在"
      fi

[[]]

  • 替代[],在字符串、文件、正则方面
  • 扩展条件测试是 Bash 的扩展测试命令,用于 字符串比较文件测试逻辑运算,比 [] 更强大。
  • 支持运算符(包含[])
    运算符 说明 示例
    == 字符串相等 [[ $str == "hello" ]]
    && 逻辑与 [[ $a -gt 3 && $b -lt 5 ]]
    || 逻辑或 [[ $a -gt 3 || $b -lt 5 ]]
    > 字典序 [[ "b" > "a" ]]
    < 字典序 [[ "a" < "b" ]]

(())

  • 替代[],在数值比较方面
  • 用于数值比较