经常会混淆
$(( ))
、${}
、$()
这些语法的使用,刚好最近有空,就来做一下相关的总结,方便后面查询。
$
相关的语法
一、和$变量名
(一) 单纯的当我们定义完一个变量后(或者是已知环境变量中存在的变量名),那我们就可以通过在变量名前面加$
的方式来引用这些变量 下面我们用一个小案例来演示一下
#!/bin/bash
field1=Hello
field2=World
echo $field1
echo $field2
执行结果为:
Hello
World
我们可以看到,我们定义的变量是可以正常打印到控制台的
$变量
需要注意的细节
使用- 变量名后面不要直接加其他字符串,防止识别错误。我们可以看看下面这个例子: 我们定义了变量
field1
的值为Hello
,希望输出HelloWorld
。我们尝试直接在$field1
后面加上World
字符串,看一下输出的结果
#!/bin/bash
field1=Hello
echo '------------'
echo $field1World
echo '------------'
可以发现,打印出来的结果是空。这是因为字符串和变量名中间没有空格的话,脚本在执行的过程中会把field1World
看成是一整个的变量名,而这个变量名我们没有定义,所以自然是找不到结果的。
------------
------------
${变量名}
(二)${变量名}
和$变量名
的效果差不多,作用是引用我们定义的变量(包括环境变量),但${变量名}
可以显式地标识我们希望引用的具体的变量,我们可以通过上文的案例来进行演示:
#!/bin/bash
field1=Hello
echo '------------'
echo ${field1}World
echo '------------'
执行结果为:
------------
HelloWorld
------------
我们可以发现,即使字符串World
和变量之间不需要空格,脚本执行的时候也可以正常引用变量。
$( 脚本 )
(三)在执行一条命令时,shell会将$()
中的语句当做命令执行一遍,再将结果加入到原命令中重新执行。简单概括的话,$( 脚本 )
可以让我们获取到命令执行的结果值。 下面我们来用一个小案例来演示一下,结合echo
命令来输出当前日期
#!/bin/bash
echo '------------'
echo "current date is $(date +%Y-%m-%d)"
echo '------------'
执行结果如下:
------------
current date is 2023-06-15
------------
我们可以看到,脚本在执行的过程中,确实是先把$()
的内容执行后,再加入到了最终的文本中。需要注意的是,输出echo的内容的时候,不可以使用''
,单引号里面的内容会被当做普通文本来处理。
PS:这里稍微拓展一下,脚本
和$(脚本)
这两个语法实现的效果是一致的,所以有时候我们会看到有些人是用脚本
的方式来获取脚本的执行结果的。
$(( 运算式 ))
和 $[]运算式
(四)这两个语法主要是用来帮助我们做一些计算的。我们知道在shell脚本中,我们定义的数字默认都会被识别为字符串。所以涉及到数值运算的话,我们可以借助$(( 运算式 ))
来帮助我们完成一些计算。 下面我们用一个案例来简单演示一下:
#!/bin/bash
result1=$((1+2+3))
result2=1+2+3
result3=$[1+2+3]
echo '------------'
echo "1+2+3=${result1}"
echo "1+2+3=${result2}"
echo "1+2+3=${result3}"
echo '------------'
从结果中我们可以看到,使用直接用1+2+3
是得不到计算结果的,使用$(())
或者$[]
就可以正常拿到计算结果了。
------------
1+2+3=6
1+2+3=1+2+3
1+2+3=6
------------
$
有关的特殊变量
(五)和在shell脚本中,除了我们自定义的变量以及环境变量外,shell中还存在着一些自带的特殊变量来供我们使用。这些特殊变量在我们跑一些比较复杂的脚本的时候,给予很大的帮助。
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n (n>1) | 传递给脚本或函数的参数。n是一个数字,表示第几个参数。例如,第一个参数是2。若n大于10,则语法为${n} |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或者函数的所有参数 |
$@ | 传递给脚本或函数的所有参数。当被双引号"" 包含时,$@ 和@* 稍有不同 |
$? | 上个命令的退出状态,或函数的返回值 |
$$ | 当前Shell进程ID。对于Shell脚本,就是这些脚本所在进程ID |
下面我们用一个简单的案例来演示一下,脚本内容如下:
#!/bin/bash
echo "====================="
echo "当前脚本文件名$0= $0"
echo "第一个参数$1= $1"
echo "第二个参数$2= $2"
echo "所有参数个数$#= $#"
echo "所有参数$*= $*"
echo "所有参数$@= $@"
echo "当前进程ID$$= $$"
echo "====================="
脚本执行结果如下,我们可以看到基本上相关的数据都正确打印出来了。
[root@10-60-159-92 testssh]# sh test.sh aa bb cc
=====================
当前脚本文件名test.sh= test.sh
第一个参数aa= aa
第二个参数bb= bb
所有参数个数3= 3
所有参数aa bb cc= aa bb cc
所有参数aa bb cc= aa bb cc
当前进程ID1432997= 1432997
=====================
$*
和$@
的区别
关于在上一个案例中,我们会发现$*
和$@
打印出来的结果是一样的,那实际上这两个特殊变量有存在什么区别吗?如果这两个特殊变量没有被""
包含的时候,其实是没有区分的。但当他们被""
包含时,区别就显示出来了:$\*
把所有的参数看做一个整体,而$@
把每个参数区分对待。具体的区别我们可以用一个案例来演示一下:
#!/bin/bash
echo "====================="
echo "print all params by \"\$*\""
for var in "$*"
do
echo $var
done
echo "====================="
echo "====================="
echo "print all params by \"\$@\""
for var in "$@"
do
echo $var
done
echo "====================="
执行结果如下,我们可以发现,对于$@
而言,它会自动将所有的变量当做一个个元素单独去处理。
[root@10-60-159-92 testssh]# sh test.sh aa bb cc
=====================
print all params by "$*"
aa bb cc
=====================
=====================
print all params by "$@"
aa
bb
cc
=====================
对于特殊变量的使用,需要注意我们反而不能使用例如:${0}
或者${$0}
来获取当前脚本的文件名,因为0
或者$0
并不是我们定义的变量名,使用${}
反而会识别不出来。所以对于特殊变量,我们正常使用就行。同时,平时我们写脚本的时候,相关的变量名也尽量不要和这些特殊变量重复,避免脚本执行错误。
java sh
可以使用命令
sh xxx.sh
执行,也可以使用./xxx.sh
执行。sh xxx.sh
与./xxx.sh
区别sh xxx.sh
是不需要有执行权限./xxx.sh
是需要有执行权限的,可以通过chmod +x xxx.sh
赋予权限。
#!/bin/bash
#这里可替换为你自己的执行程序,其他代码无需更改
APP_NAME=springboot.jar
APP_DIR=/usr/local/app
#APP_DIR=`pwd`
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh sms.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
is_exist(){
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
echo "ps number is: ${pid}"
#如果不存在返回1,存在返回0 help test 查看 -t 的含义
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is already running. pid=${pid} ."
else
nohup java -jar $APP_DIR/$APP_NAME > $APP_DIR/log.out 2>&1 &
#nohup java -jar $APP_DIR/$APP_NAME
echo "${APP_NAME} start success"
fi
}
#停止方法
stop(){
is_exist
if [ $? -eq "0" ]; then
kill -9 $pid
else
echo "${APP_NAME} is not running"
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is running. Pid is ${pid}"
else
echo "${APP_NAME} is NOT running."
fi
}
#重启
restart(){
stop
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac