本篇主要介绍Shell变量相关,包括变量基础知识、变量使用进阶、位置参数的使用、特殊变量的使用、为变量定义默认值以及变量值截取、变量值替换等。
1,变量基础知识
1.1、变量定义
如下为几个简单的变量示例
MY_VAR="Hello, World!"
MAX_COUNT=10
FILE_PATH="/home/user/file.txt"
常见的规范:
- 在 Shell 中定义变量时,变量名和等号之间不能有空格。
- 变量名通常使用大写字母,以便与命令和其他变量区分开来,变量名包含多个单词时使用下划线进行分隔。
- 变量值尽量使用双引号包围起来,以防止值中存在空格或特殊字符引发错误。
- 变量值可以包含其他变量,但是需要使用花括号 {} 来明确变量的边界。
1.2、变量使用
引用变量时,需要在变量前加上美元符号 $ :
NAME="tigerhhzz"
echo "My name is $NAME"
2,变量使用进阶
2.1、变量值中包含变量
基于执行时间写入新的日志文件:
[root@tigerhhzz01 test]# cat t1.sh
#!/bin/bash
LOG_PATH="/root/test"
NOW_TIME="$(date +%Y%m%d_%H%M%S)"
LOG_FILE="${LOG_PATH}/start_${NOW_TIME}.log"
echo "当前日志将写入文件:${LOG_FILE}"
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t1.sh
当前日志将写入文件:/root/test/start_20241001_200101.log
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t1.sh
当前日志将写入文件:/root/test/start_20241001_200104.log
[root@tigerhhzz01 test]#
2.2、截取字符串内容同时定义多个变量
使用 eval 和 awk 命令实现,将字符串中空格分隔的多个字段分别赋值给指定变量。
[root@tigerhhzz01 test]# cat t2.sh
#!/bin/bash
NOW_LINE="1008858 tigerhhzz 18"
eval $(echo "$NOW_LINE" |awk '{printf("KEY_ID=%s; KEY_NAME=%s; KEY_AGE=%s",$1,$2,$3)}')
echo "ID:${KEY_ID} ,姓名:${KEY_NAME} , 年龄:${KEY_AGE}"
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t2.sh
ID:1008858 ,姓名:tigerhhzz , 年龄:18
[root@tigerhhzz01 test]#
2.3、获取用户的输入定义变量
使用 read 命令实现,可以读取定义单个变量或读取定义多个变量(以空格分隔多个值)。
[root@tigerhhzz01 test]# cat t3.sh
#!/bin/bash
echo "请输入空格分隔的两个内容:"
read KEY_NAME KEY_AGE
echo "第一个值为:${KEY_NAME},第二个值为:${KEY_AGE}"
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t3.sh
请输入空格分隔的两个内容:
tigerhhzz 18
第一个值为:tigerhhzz,第二个值为:18
[root@tigerhhzz01 test]#
也可以使用 -p 选项设置输入提示符:
[root@tigerhhzz01 test]# cat t3-2.sh
#!/bin/bash
read -p "请输入您的国家: " KEY_COUNTRY
echo "您输入的国家是: ${KEY_COUNTRY}"
[root@tigerhhzz01 test]# sh t3-2.sh
请输入您的国家: 中国
您输入的国家是: 中国
[root@tigerhhzz01 test]#
3,位置参数的使用
在 Shell 脚本中,你可以使用位置参数来处理用户输入的传参。位置参数是传递给脚本或函数的参数,通常通过 $1, $2, $3 … $9 等等来访问(超过9个的位置参数引用时需要使用花括号围起来,例如使用 ${10} 来获取第10个参数的值)。如果你希望处理任意数量的参数,你还可以使用 $@ 和 $* 来引用所有的参数。另外可以使用 $0 获取脚本的名称,使用 $# 来获取传递给脚本的参数的个数。
[root@tigerhhzz01 test]# cat t4.sh
#!/bin/bash
# 打印第一个和第二个参数
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "当前 Shell 脚本名称为:$0 ,你总共输入了 $# 个参数"
[root@tigerhhzz01 test]# sh t4.sh a b c
第一个参数: a
第二个参数: b
当前 Shell 脚本名称为:t4.sh ,你总共输入了 3 个参数
[root@tigerhhzz01 test]#
3.1、不被双引号包围
在 Shell 脚本中引用所有的参数时,如果 $* 和 $@ 不被双引号包围,它们之间没有任何区别,都将接收到的每个参数视为独立的单元,参数之间以空格分隔。
[root@tigerhhzz01 test]# cat t4-2.sh
#!/bin/bash
echo "如下为 \$*"
for i in $* ; do
echo $i
done
echo "如下为 \$@"
for i in $@ ; do
echo $i
done
[root@tigerhhzz01 test]# sh t4-2.sh a b c
如下为 $*
a
b
c
如下为 $@
a
b
c
[root@tigerhhzz01 test]#
3.2、被双引号包围
如果被双引号包围起来,区别就显现出来了。 $*会将所有参数视为一个整体(作为一个单一的字符串处理),而 $@ 仍然将每个参数视为独立的单元。这种区别在处理参数时尤为重要。
[root@tigerhhzz01 test]# cat t4-3.sh
#!/bin/bash
echo "如下为 \$*"
for i in "$*" ; do
echo $i
done
echo "如下为 \$@"
for i in "$@" ; do
echo $i
done
[root@tigerhhzz01 test]# sh t4-3.sh a b c
如下为 $*
a b c
如下为 $@
a
b
c
[root@tigerhhzz01 test]#
4,特殊变量的使用
除了上面的位置参数外,在 Shell 脚本中还有一些其他的特殊变量,如下所示。
4.1、$? 获取上一个命令的退出状态码
值为 0 表示执行成功,非 0 表示执行失败。
[root@tigerhhzz01 test]# cat t5-1.sh
#!/bin/bash
echo "$1" |grep hello
echo "grep 命令退出状态码为:$?"
[root@tigerhhzz01 test]# sh t5-1.sh
grep 命令退出状态码为:1
[root@tigerhhzz01 test]# sh t5-1.sh hello
hello
grep 命令退出状态码为:0
[root@tigerhhzz01 test]#
4.2、$$ 获取当前脚本的进程ID(PID)
[root@tigerhhzz01 test]# cat t5-2.sh
#!/bin/bash
echo "当前脚本的进程ID为:$$" >/root/test/my.pid
sleep 100
[root@tigerhhzz01 test]# nohup sh t5-2.sh &
[1] 1085578
[root@tigerhhzz01 test]# nohup: ignoring input and appending output to 'nohup.out'
[root@tigerhhzz01 test]# cat my.pid
当前脚本的进程ID为:1085578
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# ps -ef |grep t5-2 |grep -v grep
root 1085578 1085369 0 20:32 pts/0 00:00:00 sh t5-2.sh
[root@tigerhhzz01 test]#
4.3、$! 获取最后一个后台运行进程的ID(PID)
[root@tigerhhzz01 test]# cat t5-3.sh
#!/bin/bash
nohup sh /root/test/t5-2.sh &
echo "上一个后台运行的进程的PID为:$!"
[root@tigerhhzz01 test]# sh t5-3.sh
上一个后台运行的进程的PID为:1085609
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# ps -ef |grep t5-2 |grep -v grep
root 1085609 1 0 20:38 pts/0 00:00:00 sh /root/test/t5-2.sh
[root@tigerhhzz01 test]#
4.4、$- 获取当前shell选项
[root@tigerhhzz01 test]# cat t5-4.sh
#!/bin/bash
echo $-
[root@tigerhhzz01 test]# sh t5-4.sh
hB
[root@tigerhhzz01 test]# sh -x t5-4.sh
+ echo hxB
hxB
[root@tigerhhzz01 test]#
5,为变量设置默认值
常用有两种。当变量没有被定义或为空时,一种只返回默认值不会修改变量,另一种则会设置变量为默认值。
5.1、:-
如果变量 VAR 没有被定义或为空,则返回默认值(VAR本身没有任何改变)。
[root@tigerhhzz01 test]# cat t6-1.sh
#!/bin/bash
echo "如下为未定义变量时"
unset VAR
RESULT=${
VAR:-"默认值"}
echo "RESULT: $RESULT"
echo "VAR: $VAR"
echo "如下为定义变量后"
VAR="Hello"
RESULT=${
VAR:-"默认值"}
echo "RESULT: $RESULT"
echo "VAR: $VAR"
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t6-1.sh
如下为未定义变量时
RESULT: 默认值
VAR:
如下为定义变量后
RESULT: Hello
VAR: Hello
[root@tigerhhzz01 test]#
5.2、:=
如果变量 VAR 没有被定义或为空,则设置变量 VAR 的值为默认值,并返回其值(VAR发生改变)。
[root@tigerhhzz01 test]# cat t6-2.sh
#!/bin/bash
echo "如下为未定义变量时"
unset VAR
RESULT=${
VAR:="默认值"}
echo "RESULT: $RESULT"
echo "VAR: $VAR"
echo "如下为定义变量后"
VAR="Hello"
RESULT=${
VAR:="默认值"}
echo "RESULT: $RESULT"
echo "VAR: $VAR"
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t6-2.sh
如下为未定义变量时
RESULT: 默认值
VAR: 默认值
如下为定义变量后
RESULT: Hello
VAR: Hello
[root@tigerhhzz01 test]#
6、变量值截取
6.1、获取变量值的字符个数
[root@tigerhhzz01 test]# cat t8-1.sh
#!/bin/bash
VAR="$1"
echo "输入的字符长度为:${#VAR}"
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t8-1.sh
输入的字符长度为:0
[root@tigerhhzz01 test]#
[root@tigerhhzz01 test]# sh t8-1.sh hello
输入的字符长度为:5
[root@tigerhhzz01 test]#
6.2、截取变量值的指定个数字符
从左边开始
// 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR:0:5}
https
[root@tigerhhzz01 test]#
从左边开始
// 其中的 0-10 表示右边算起第十个字符开始,5 表示字符的个数。
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR:0-10:5}
index
[root@tigerhhzz01 test]#
6.3、截取指定位置到结束字符
从左到右数第几个字符开始到结束
// 其中的 8 表示左边第9个字符开始,一直到结束。
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR:8}
www.example.com/index.html
[root@tigerhhzz01 test]#
从右到左第几个字符开始到结束
// 表示从右边第四个字符开始,一直到结束。
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR:0-4}
html
[root@tigerhhzz01 test]#
6.4、截取变量值保留右边字符
一个#符号截取,最短匹配
// 其中 VAR 是变量名,#符号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符,即删除 https://
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR#*//}
www.example.com/index.html
[root@tigerhhzz01 test]#
两个#符号截取,最长匹配
// 其中 ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符,即删除 https://www.example.com/
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR##*/}
index.html
[root@tigerhhzz01 test]#
6.5、截取变量值保留左边字符
一个%符号截取,最短匹配
// 其中 %/* 表示从右边开始,删除第一个 / 号及右边的字符,即删除 /index.html
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR%/*}
https://www.example.com
[root@tigerhhzz01 test]#
两个%符号截取,最长匹配
// 其中 %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符,即删除 //www.example.com/index.html
[root@tigerhhzz01 test]# VAR=https://www.example.com/index.html
[root@tigerhhzz01 test]# echo ${VAR%%/*}
https:
[root@tigerhhzz01 test]#
7、变量值替换
7.1、字母大写转换为小写
两个 , 符号,如果变量 VAR 中包含大写字母,则这些字母都会被转换为小写字母。
[root@tigerhhzz01 test]# VAR="Hello, World!"
[root@tigerhhzz01 test]# echo "${VAR,,}"
hello, world!
[root@tigerhhzz01 test]#
单个 , 符号,如果变量 VAR 中首个字符为大写字母,则这个字母将被转换为小写字母。
[root@tigerhhzz01 test]# VAR="Hello, World!"
[root@tigerhhzz01 test]# echo "${VAR,}"
hello, World!
[root@tigerhhzz01 test]#
7.2、字母小写转换为大写
两个 ^ 符号,如果变量 VAR 中包含小写字母,则这些字母都会被转换为大写字母。
[root@tigerhhzz01 test]# VAR="Hello, World!"
[root@tigerhhzz01 test]# echo "${VAR^^}"
HELLO, WORLD!
[root@tigerhhzz01 test]#
单个 ^ 符号,如果变量 VAR 中首个字符为小写字母,则这个字母将被转换为大写字母。
[root@tigerhhzz01 test]# VAR="hello, World!"
[root@tigerhhzz01 test]# echo "${VAR^}"
Hello, World!
[root@tigerhhzz01 test]#
7.3、字符替换
单个 / 符号,替换第一个匹配的字符
[root@tigerhhzz01 test]# VAR="hello,zhangsan. hello lisi"
[root@tigerhhzz01 test]# echo ${VAR/hello/nihao}
nihao,zhangsan. hello lisi
[root@tigerhhzz01 test]#
两个 / 符号,替换所有匹配的字符
[root@tigerhhzz01 test]# VAR="hello,zhangsan. hello lisi"
[root@tigerhhzz01 test]# echo ${VAR//hello/nihao}
nihao,zhangsan. nihao lisi
[root@tigerhhzz01 test]#
不要停止奔跑,不要回顾来路,来路无可眷恋,值得期待的只有前方。