shell变量

2,746 阅读4分钟
原文链接: rangaofei.github.io
1. 变量设置
<variable>=<value>  #为变量赋值
echo $<variable>    #输出变量的值
echo ${<variable>}  #输出变量的值,效果同上
unset variable      #取消变量的值
  1. 变量与值之间以一个=连接
  2. 等号两边不能有空格
  3. 变量名称只能是英文字母与数字,且不能以数字开头
  4. 变量内容如果有空格可以使用双引号或者单引号将内容包裹起来。一般情况下,变量内容中含有变量的引用,也就是包含$<variable>,则用双引号包裹,一般字符则用单引号包裹。
  5. 可以使用转义字符“\”来使特殊符号变为一般符号。
  6. 假如变量内容中包含其他命令提供的信息,则需要使用以下两种形式:

    • `\ `

    • $(<command>)

  7. 若为变量增加内容时,可以使用$(<variable>)addition或者$<variable>addition形式。
    例如:

    
    8. `export`关键字用来设置环境变量,可以传递给当前bash和子进程。
    9. 通常大写字母为系统默认变量,小写字母为自己设置的变量。例如`PATH,HOME,SHELL`等,均为系统变量。
    
    下面写一个简单的例子来验证上面的语法:
    
    ```shell
    tmp="I am tmp"                      #*定义变量,=两边不能有空格,否则报错
    echo "first type $tmp"              #*"$<variable>"形式输出变量
    echo "second type ${tmp}"           #*"${<variable>}"另一种形式输出变量
    echo 'third type ${tmp}'            #*'$<variable>'不能输出变量
    echo "with acutual '$' is \$tmp"    #*用转义字符输出特殊字符
    version=$(uname -r)                 #*$(command)方式获取函数的值
    echo "first $version"
    version=`pwd`                       #*`command`方式获取函数的值
    echo "second $version"
    unset version                       #*删除变量的值
    echo "no version $version"          #*不输出任何内容
    tmp="${tmp} add new words"          #*为tmp添加内容,注意$取变量的格式
    echo $tmp                           #*输出添加后的内容
    var="parent process var"
    export var                          #*输出变量var到子线程
    echo "parent pid=?"
    

注释已经解释的很好了,查看输出内容:

first type I am tmp
second type I am tmp
third type ${tmp}
with acutual '$' is $tmp
first 17.4.0
second /Users/saka/Downloads/Markdown/shell命令
no version
I am tmp add new words
parent pid=19895
2. 变量的作用域

变量的作用域分为环境变量、全局变量、局部变量。

  • 环境变量是系统中已经定义好的变量,输入env即可:
SHELL=/bin/zsh
TMPDIR=/var/folders/1x/gcpxck2s0jxbfs6qll8p0jlh0000gn/T/
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.X4uBMH5DE9/Render
TERM_PROGRAM_VERSION=1.20.0
ZSH=/Users/saka/.oh-my-zsh
USER=saka
COMMAND_MODE=unix2003
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
PWD=/Users/saka/Downloads/Markdown/shell命令
LANG=zh_CN.UTF-8
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
var=parent process var
VSCODE_NODE_CACHED_DATA_DIR_18562=/Users/saka/Library/Application Support/Code/CachedData/c63189deaa8e620f650cc28792b8f5f3363f2c5b
SHLVL=30
HOME=/Users/saka
VSCODE_NLS_CONFIG={"locale":"zh-cn","availableLanguages":{"*":"zh-cn"}}
LESS=-R

这些变量都可以直接在shell脚本中获取。

  • 全局变量
    shell脚本,包括shell脚本中的函数中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止。
  • 局部变量
    函数定义的变量可以被显示定义成local的,其作用域局限于函数内。但请注意,函数的参数是local的。如果变量同名,Shell函数定义的local变量会屏蔽脚本定义的global变量。

一个简单的例子说明:

echo "env variable SHELL=${SHELL}"          #*输出环境变量SEHLL的默认值
function showshell(){                       #*定义一个函数
    SHELL="custom shell"                    #*将SHELL设置为自己需要的变量
    local var="local var"                   #*定义函数内的局部变量
    echo "function SHELL=$SHELL"            #*输出SHELL,已变为自定义变量
    echo "local var=${var}"                 #*输出局部变量,有效
}
showshell                                   #*执行函数showshell
echo "after showshell SHELL=${SHELL}"       #*输出SHELL,函数外有效
echo "local var=${var}"                     #*输出函数内的局部变量,无效
unset SHELL
echo "after unset SHELL=${SHELL}"           #*执行unset后,变量已无值,包括环境变量

查看输出结果:

env variable SHELL=/bin/zsh
function SHELL=custom shell
local var=local var
after showshell SHELL=custom shell
local var=
after unset SHELL=
3. 对变量的操作

首先来看一张总的表:

  • 变量的替换与删除
变量设置方式 说明
${变量#关键字} 若变量内容从头开始的数据符合“关键字”,则将符合的最短数据删除
$(变量##关键字) 若变量内容从头开始的数据符合“关键字”,则将符合的最长数据删除
${变量%关键字} 若变量内容从末端向前的数据符合“关键字”,则将符合的最短数据删除
${变量%%关键字} 若变量内容从末端向前的数据符合“关键字”,则将符合的最长数据删除
${变量/旧字符串/新字符串} 若变量内容符合“旧字符串”,则第一个旧字符串会被新字符串替换
${变量//旧字符串/新字符串} 若变量内容符合“旧字符串”,则全部的旧字符串会被新字符串替换
path="abcdeaAbcedeA"
echo "字符*匹配任意个字符,下边是原有的值"
echo $path
echo "从开始位置匹配第一个'a',然后一直删除到第一个碰到的'de'"
echo ${path#a*de}
echo "从开始位置匹配到第一个'a',然后一直删除到最后一个碰到的'de'"
echo ${path##a*de}
echo "从末尾开始匹配到第一个'A',然后一直删除到向前寻找到的第一个'c'"
echo ${path%A*c}
echo "从末尾开始匹配到第一个'A',然后一直删除到向前寻找到的最后一个'c'"
echo ${path%%A*c}
echo "替换一个a为Z"
echo ${path/a/Z}
echo "替换所有的a为Z"
echo ${path//a/Z}

输出结果:

字符*匹配任意个字符,下边是原有的值
abcdeaAbcedeA
从开始位置匹配第一个'a',然后一直删除到第一个碰到的'de'
aAbcedeA
从开始位置匹配到第一个'a',然后一直删除到最后一个碰到的'de'
A
从末尾开始匹配到第一个'A',然后一直删除到向前寻找到的第一个'c'
abcdeaAbcedeA
从末尾开始匹配到第一个'A',然后一直删除到向前寻找到的最后一个'c'
abcdeaAbcedeA
替换一个a为Z
ZbcdeaAbcedeA
替换所有的a为Z
ZbcdeZAbcedeA
  • 变量的设置
设置方式 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} str=expr
var=expr
str不变
var=
str不变
var=$str
var=${str:=expr} str=expr
var=expr
str=expr
var=expr
str不变
var=$str
var=${str?expr} expr输出到stderr var= var=str
var=${str:?expr} expr输出到stderr expr输出到stderr var=str

这个比较简单,不写测试用例。主要说明一下’-‘和’:’:

假如-前边的变量未设置值,则取后边的变量假如前边的变量已经设置值,则输出前边的变量。
假如:-一同使用,则前边的变量未设置或者值为””,则用后边的值替换前边的值,否则不替换

4. 变量的声明
  • 通过用户输入设置变量的值

声明形式

read [-pt] <variable>
参数:
-p : 后面接提示的内容
-t : 后面接等待的时间,单位为秒

编写一个简单的脚本测试:

#/bin/zsh
echo "请根据下面的提示输入你想要设置的值"
read -p "var1= " var1
read -p "var2= " var2
read -p "你已经输入了所有的变量值,是否立即打印?y/n:" print
if [ ${print}x == yx ];then
    echo "var1= $var1"
    echo "var2= $var2"
elif [ ${print}x == nx ];then
    echo "complete"
else
    echo unknow command
fi

执行即可:

请根据下面的提示输入你想要设置的值
var1= 9
var2= 8
你已经输入了所有的变量值,是否立即打印?y/n:y
var1= 9
var2= 8
  • declare/typeset

定义形式

declare [-aixrp] variable
参数:
-a : 将变量定义为数组类型
-i : 将变量定义为整型
-x : 将变量输出为环变量
-r : 将变量设置为只读类型(readonly),相当于java中的常量

declare -x <variable>能将变量提升为环境变量,declare +x <varibale>能将变量取消为环境变量。

bash中的变量假如不是用声明方式,默认都是字符串。声明后可以进行简单的操作。一个简单的例子说明:

#bin/bash
sum_one=100+10          #*直接声明,是字符串格式
echo $sum_one           #*输出100+10
declare -i sum          #*声明为整型
sum=100+10              #*计算结果
echo $sum               #*输出为110
declare -a array        #*定义数组
array[1]="a"            #*定义元素1
array[2]="b"            #*定义元素2
echo ${array[*]}        #*输出数组
100+10
110
a b