bash 变量

Created

2023-09-12 17:30:16

Updated

2024-10-28 12:38:21

1 环境变量

env # 打印所有环境变量
printenv # 同上
echo $HOME # 打印某个变量的值
printenv HOME # 同上

# 一些常用的环境变量
echo $PWD
echo $HOST # 当前主机名
echo $IFS # 词与词的分隔符, 默认为空格
echo $RANDOM #返回一个0到32767之间的随机数
echo $SHELL  # 当前使用的Shell  比如 /bin/bash 或/bin/zsh

2 自定义变量

echo $ff # 没有定义的变量名 ,默认是空
a=1 # 两边不能用空格
# 这个相当于 "a=" 然后 执行1 这个命令
# 提示 没有1 这个命令
a= 1
a =1 # 同样 ,会将a 作为命令 执行,提示没有该命令

str="hello world" # 用空格 用"" 包起来
echo $str  # hello world, 默认会将多个空格合并成一个
str="hello     world"
echo $str  # hello world
echo "$str"  # hello     world
python_version=3.10
python=snake
# $ 会将后面的字符串视为变量名
echo $python_version # 3.10
# 使用{} 将变量名包起来
echo ${python}_version # snake_version
变量的值当成变量名
a=b
c=a
echo $c # a
echo ${!c} # b
a=1
unset a
# 设置为空, 就是删除, 前面说到,不定义,默认就是空
a=''
a=
a=1 # 只能在当前shell可用,
export a # 这样 在当前shell创建的子shell都可以使用该变量
export b=2 # 直接赋值export
# b 不为空,则返回b的值, 否则返回 123
a=${b:-123}
echo $a # 123 ,b还是空的
# b 不为空,则返回b的值, 否则设置b为123,并且返回123
a=${b:=123}
echo $a,$b # 123,123
# c 不为空,则返回1, 否则返回空
# 可以用来判断c 是否为空,返回1 就是不为空了
echo ${c:+1} #
c=2
echo ${c:+1} # 1

# 如果d变量未定义,则报错退出 ,错误信息是你写的 undefined
# 用来防止变量未定义
${d:?undefined} # -bash: d: undefined
脚本中应用
# 使用 1 到 9 表示参数
#!/bin/bash
${1:?"请带上参数"}

3 局部变量和全局变量

#!/bin/bash
a=1
foo(){
    b=2 # 执行foo函数后, b是全局变量
    local c=3 # 局部变量
    local a=4 # 与外部的a 是不一样的变量
}
foo
echo $a # 1
echo $b # 读取的到
echo $c # 读取不到
bar(){
    echo $b
}
bar # 会打印 b的值

4 $开头的特殊变量

# 上一个命令的退出码,我们用来判断命令执行是否成功
lss
echo $?  # > 0 表示执行失败, 0 表示成功

# $$为当前Shell的进程ID
echo $$

#$_ 上一个命令的最后一个参数
ls tmp_install
echo $_ # tmp_install
脚本a.sh
#!/bin/bash

echo $0
echo $1
echo $2
echo $*
echo $@
echo $#
# 看看$@ $* 之间的区别
for var in "$*"
do
    echo "$var"
done

for var in "$@"
do
    echo "$var"
done
执行 ./a.sh a b c 的结果
./a.sh  # $0 脚本本身
a       # $1 第一个参数
b       # $2 第二个参数
a b c   # $* 所有参数
a b c   # $@ 所有参数
3       # $# 参数个数
a b c   # "$*" 参数作为一个整体
a       # "$@" 还是会
b
c

5 declare / typeset

Tip

declare和typeset 等价

5.1 打印当前环境所有变量

# 不带参数
declare
typeset

5.2 申明为只读

# 只读, 修改会报错
declare -r a=1
a=2  # -bash: a: readonly variable
unset a  # -bash: unset: a: cannot unset: readonly variable

5.3 申明为整型

a1=1
a2=2
c=b1+b2
echo $c  # 结果是  b1+b2
# 我们计算是要这样的
a4=$((a1 + a2))  # 或a3=$(($a1 + $a2))
# 申明为整型
declare -i a1=1 a2=2
declare -i res
res=a1+a2
echo $res # 3
res=a1+a2 # 3 这样其实就ok的, 只要 结果的变量设置为整型,a1和a2 不需要设置.
res=a1+10 # 11

d=1+2
echo d # 1+2
declare -i d
d=1+2
echo d # 3

5.4 声明变量为大/小写字母

# 申明为小写
declare -l a
a=AbC
echo $a # abc
# 申明为大写
declare -u b
b=abc
echo $b # ABC
# 取消变量b 的大写申明
declare +u b # - 变+ 都有类似效果
b=abc
echo $b # abc 不再会变成ABC了

5.5 申明为环境变量

a=1
declare -x a # 同export a

5.6 显示当前环境的所有函数

# 打印当前环境的所有函数名 以及 定义
declare -f
# 只打印函数名
declare -F

6 字符串

6.1 拼接

str1="hello"
str2="world"
result="$str1 $str2"

6.2 长度

str="hello world"
echo ${#str} # 输出 "11"

echo $(expr length "$str")
echo `expr length "$str"`

6.3 截取

str="hello world"
#  从第6个索引开始,包含索引位置的字符, 截取5个字符.
echo ${str:6:5} # 输出 "world"

echo ${str:2} # llo world
# 同上
echo ${str:(2)}  # llo world

# : 后面必须有空格. -2 表示从尾部开始找
echo ${str: -2} #ld
# 同上
echo ${str:(-2)} #ld
echo ${str: -5:2} # wo
echo ${str:(-5):2} # wo
Caution
  1. expr index 命令只能查找单个字符或字符串中的第一个字符,不能查找多个字符组成的子串
  2. 如果是子串,那会将子串里的每个字符全部找一遍, 然后显示最短的那个
  3. ==这里的索引是从1 开始的, 而${str:1} 是从0开始的==
str="hello world"
# 不是7 而是3?  这是因为它会将你的字串里的每个字符全部找一遍, 然后显示最短的那个
# w 是在 第7个位置, o在 5,  而l 是在3 最短
expr index "$str" "world" # 3
expr index "$str" "worle" # 2

# 我们应该这样使用这个
expr index "$str" "w"  # 7
Tip

所以这个的用法 就不该整子串, 而是用来找单个字符的操作

Warning

必须是从头开始找的

str="hello world"
expr match "$str" world # 0
expr match "$str" hell # 4
expr match "$str" hellq # 0

6.4 替换

str="hello hello world"
echo ${str/hello/goodbye} # 输出 "goodbye hello world"
str="hello hello world"
echo ${str//hello/goodbye} # 输出 "goodbye goodbye world"

6.5 删除(替换为空)

最短匹配
str="hello world hello python"
echo ${str#*llo} # world hello python
最长匹配
str="hello world hello python"
echo ${str##*llo} # python
最短匹配
str="hello world hello python"
echo ${str%llo*} # hello world he
最长匹配
str="hello world hello python"
echo ${str%%llo*} # he

6.6 大小写转换

str="Hello World"
echo ${str,,} # 输出 "hello world"
str="hello world"
echo ${str^^} # 输出 "HELLO WORLD"

7 数组

Tip
  • 整型数组无需用declare -a arr 进行申明
  • 关联数组必须要declare -A arr 进行申明

7.1

arr[0]=a
arr[1]=b
arr[2]=c
arr=(a b c) # 索引按顺序
arr=([0]=c [1]=a [2]=b) # 指定索引
touch a.txt b.txt c.txt
arr=(x *.txt)
echo ${arr[0]} # x
echo ${arr[1]} # a.txt

arr2=(x $(ls *.txt))
read -a arr # 输入 a b c
echo ${arr[0]} # a
arr=(a b c)
arr+=(1 2 3)
echo ${arr[@]} # a b c 1 2 3 

7.2

arr=(a b c)
echo ${arr[0]} # a
echo $arr  # 输出 首个元素的值
echo $arr[0] # 输出 a[0]  ,{} 是必须的.
arr=(a b c)
echo ${arr[@]} # a b c
echo ${arr[*]}
arr=([5]=1 [2]=4 [10]=1)
echo ${#arr[*]} #3
echo ${#arr[@]} #3
索引0的元素的长度
arr=(abc e fg)
echo ${#arr[0]} #3
arr=([5]=1 [2]=4 [10]=1)
echo ${!arr[@]} # 打印索引 2 5 10
echo ${!arr[*]} # 同上
arr=(a b c)
for i in ${!arr[@]}
do
    echo ${arr[i]}
done
Tip

与字符串截取类似

arr=(a b c e f g)
# ${arr[@]:position:length}
echo ${arr[@]:1:2} # b c
# 省略 length
echo ${arr[@]:2} # c e f g
echo ${arr[@]: -2} # f g
echo ${arr[@]: -3:1} # e

7.3

arr=(a b c)
echo ${!arr[@]} # 0 1 2
unset arr[0]
echo ${arr[@]} # b c
echo ${!arr[@]} # 1 2, 索引0 没有了.
unset arr # 全部删除

7.4 关联数组

Caution

需要bash 4.0 以上版本

declare -A it
it["go"]="1.19.0"
it["python"]="3.10.0"
it["rust"]="1.58.1"
Back to top