简介
Shell脚本中的变量,无论简单还是复杂,都是一个编程工具中最基础也是最有力的元素。理解变量的概念及其如何在脚本中使用,可以大大增强脚本的灵活性和功能。下面我们将详细讨论全局变量,局部变量,环境变量,特殊变量的概念和作用,并探讨 Shell 中 * 和 @ 的区别。
全局变量
全局变量是在整个脚本中都可以访问的变量,它们可以在脚本的任何位置定义和使用。使全局变量生效的命令是 export。下面有一些全局变量的示例,
以下是一些全局变量的示例:
bash:
# 示例1:定义一个全局变量并打印它
name="Linux"
echo $name
# 示例2:在函数中使用全局变量
name="Linux"
function global_demo {
echo "$name"
}
global_demo # 输出 "Linux"
# 示例3:在函数中修改全局变量的值
name="Linux"
function global_demo {
name="Shell"
echo "$name"
}
global_demo # 输出 "Shell"
echo $name # 输出 "Shell"
# 示例4:在循环中使用全局变量
count=10
while [ $count -ge 0 ]
do
echo $count
((count--))
done
# 示例5:读取用户的输入存储在全局变量中
echo "Please enter your name: "
read name
echo "Hello, $name"
# 示例6:在另一个Shell脚本中使用全局变量
export global_var="I am a global variable"
bash -c 'echo "In another shell script, global_var = $global_var"'
# 示例7:在另一个子进程中使用全局变量
export global_var="I am a global variable"
( echo "In a subshell, global_var = $global_var" )
# 示例8:全局变量在删除后不可用
export global_var="I am a global variable"
unset global_var
echo $global_var # 输出空行
# 示例9:检查全局变量是否存在
if [ -z "${var+set}" ];
then
echo "var is not set."
else
echo "var is set to '$var'"
fi
# 示例10:全局变量在同一个会话中共享
export global_var="I am a global variable"
bash -c 'global_var="Modified in another shell script"; echo $global_var'
echo $global_var # 输出 "I am a global variable"
局部变量
局部变量只能在定义它的函数或代码块中使用。如果尝试在声明局部变量的块的外部来访问它,Shell将把它视为一个未定义的新变量。我们可以用 local 关键字创建局部变量。下面的示例演示了如何在 Shell 脚本中创建和使用局部变量。
以下是一些局部变量的示例:
bash:
# 示例1:在函数中定义一个局部变量
function local_demo {
local name="Shell"
echo "$name"
}
local_demo # 输出 "Shell"
# 示例2:查看函数外部无法访问局部变量
function local_demo {
local name="Shell"
echo "$name"
}
local_demo # 输出 "Shell"
echo $name # 输出空行
# 示例3:局部变量覆盖全局变量
name="Linux"
function local_demo {
local name="Shell"
echo "$name"
}
local_demo # 输出 "Shell"
echo $name # 输出 "Linux"
# 示例4:对局部变量进行算术运算
function local_demo {
local num1=5
local num2=10
echo $((num1 + num2))
}
local_demo # 输出15
# 示例5:在循环中使用局部变量
function local_demo {
local count=5
while [ $count -gt 0 ]
do
echo $count
((count--))
done
}
local_demo #输出1 2 3 4 5
# 示例6:在函数中尝试修改另一个函数的局部变量
function func_a {
local local_var="Variable of func_a"
echo "$local_var"
}
function func_b {
local local_var="Variable of func_b"
echo "$local_var"
}
func_a # 输出 "Variable of func_a"
func_b # 输出 "Variable of func_b"
# 示例7:函数返回值作为局部变量
function add {
local sum=$(( $1 + $2 ))
echo $sum
}
result=$(add 10 20)
echo $result # 输出30
# 示例8:在函数中使用外部命令的结果作为局部变量
function current_date {
local date=$(date)
echo "Current date is: $date"
}
current_date
# 示例9:在函数中使用 read 命令输入的值作为局部变量
function get_name {
read -p "Enter your name: " local name
echo "Hello, $name"
}
get_name
# 示例10:递归函数中的局部变量
function factorial {
local value=$1
if [ $value -eq 0 ]
then
echo 1
else
echo $(( $value * $(factorial $(( $value - 1 ))) ))
fi
}
result=$(factorial 5)
echo $result # 输出 120
环境变量
环境变量是当前Shell会话或子会话中一直存在的全局变量。它们会从父会话传播到子会话。将变量导出为环境变量的命令是 export,删除环境变量的命令是 unset。
以下是一些环境变量的示例:
bash:
# 示例1:显示所有环境变量
printenv
# 示例2:显示特定环境变量
echo $HOME
# 示例3:设置新的环境变量
export NEW_VAR="New Variable"
# 示例4:删除环境变量
unset NEW_VAR
# 示例5:将环境变量传递给子进程
export VAR="value"
bash -c 'echo $VAR'
# 示例6:显示环境变量的值
echo $PATH
# 示例7:将字符串追加到环境变量
PATH=$PATH:/new/path
echo $PATH
# 示例8:创建新的环境变量并在另一个Shell脚本中使用
export NEW_VAR="New environment variable"
bash -c 'echo "In another shell script, NEW_VAR = $NEW_VAR"'
# 示例9:删除环境变量
unset NEW_VAR
echo $NEW_VAR # 输出空行
# 示例10:环境变量在同一个会话中共享
export NEW_VAR="New environment variable"
bash -c 'NEW_VAR="Modified in another shell script"; echo $NEW_VAR'
echo $NEW_VAR # 输出 "New environment variable"
特殊变量
Bash Shell 中有一些特殊的预定义变量,这些变量可以在 Shell 脚本中提供一些有用的信息,如当前脚本名称,Shell选项,Shell使用的版本号等。
以下是一些特殊变量的示例:
bash:
# 示例1:$0 是脚本的名称
echo "Script name: $0"
# 示例2:$1 到 $9 是脚本的参数
echo "First argument: $1"
echo "Second argument: $2"
# 示例3:$# 是脚本参数的数量
echo "Number of arguments: $#"
# 示例4:$@ 和 $* 是所有参数的列表
echo "All arguments with \$@: $@"
echo "All arguments with \$*: $*"
# 示例5:$ 是当前 shell 的进程 ID
echo "Process ID: $"
# 示例6:$! 是最后运行的后台进程的进程 ID
sleep 5 &
echo "Last PID: $!"
# 示例7:$? 是最后命令的退出状态
ls /wrong/path
echo "Exit status: $?" #
# 示例6:命令行参数的整个列表(所有参数作为一个字符串)
echo "$*"
# 示例7:命令行参数的整个列表(所有参数作为独立的字符串)
echo "$@"
# 示例8:上一个后台命令的进程ID
sleep 10 &
echo "PID of last background command: $!"
# 示例9:Shell脚本名称
echo "Script name: $0"
# 示例10:上一个命令的退出状态
ls /wrong/path
echo "Exit status of last command: $?"
*和@的区别
在 Shell 中,* 和 @ 都用于展开位置参数。然而,它们在双引号中的行为是不同的。$* 在双引号中将所有参数看作一个整体,而 $@ 在双引号中将每个参数看作独立的字符串。
以下是 * 和 @ 的区别的示例:
bash:
# 示例1:对比 $* 和 $@(未引用)
set -- "arg 1" "arg 2" "arg 3"
for word in $*; do echo "$word"; done
for word in $@; do echo "$word"; done
# 示例2:对比 $* 和 $@(引用)
for word in "$*"; do echo "$word"; done #输出
for word in "$@"; do echo "$word"; done #输出
# 示例6:显示所有参数(作为独立的字符串)
echo $@
# 示例7:在数组中使用 *
array=("apple" "banana" "cherry")
echo "${array[*]}" # 输出 "apple banana cherry"
# 示例8:在数组中使用 @
array=("apple" "banana" "cherry")
echo "${array[@]}" # 输出 "apple banana cherry"
# 示例9:用 * 遍历数组
array=("apple" "banana" "cherry")
for fruit in "${array[*]}"
do
echo "$fruit"
done # 一行输出 "apple banana cherry"
# 示例10:用 @ 遍历数组
array=("apple" "banana" "cherry")
for fruit in "${array[@]}"
do
echo "$fruit"
done # 分多行分别输出 "apple","banana","cherry"
在编程的过程中,了解和理解好Shell脚本中的这些变量作用域不仅仅会使你的代码更易于理解和维护,也帮助你避免一些常见的编程错误。尤其是在处理特殊变量与区分*与@的时候,更可以增添你脚本的灵活性和多功能性。希望本篇文章能为你提供帮助,让你在编写Shell脚本的道路上更加游刃有余。