shell中特殊的变量
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
basename 是去除目录后剩下的名字
example:shell>temp=/home/temp/1.test
shell>base=`basename $temp`
shell>echo $base
结果为:1.test
dirname 是取目录
example:shell>temp=/home/temp/1.test
shell>dir=`dirname $temp`
shell>echo $dir
结果为:/home/temp
另一种实现的方法:
${var##*/} 就是把变量var最后一个/以及左边的内容去掉
${var%/*} 就是把变量var最后一个/以及右边的内容去掉
区别:@*
- 相同点:都是引用所有参数
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数(分别存储在12 3)则"*" 等价于 “12 3"(传递了一个参数);而“@" 等价于 "1""2" "$3"(传递了三个参数)
条件表达式
如果你忘记了以下的使用方式,你可以使用man test 查看. (2023年5月8日10:29:12 刚刚get到的技能)
文件表达式 if [ -f file ] 如果文件存在 if [ -d ... ] 如果目录存在 if [ -s file ] 如果文件存在且非空 if [ -r file ] 如果文件存在且可读 if [ -w file ] 如果文件存在且可写 if [ -x file ] 如果文件存在且可执行 文件系统相关 -a 文件存在,则为真(TRUE)。 -b 文件存在并且是块设备,则为真(TRUE)。 -c 文件存在并且是字符设备,则为真(TRUE)。 -d 文件存在并且是目录,则为真(TRUE)。 -e 文件存在,则为真(TRUE)。跟-a的作用一致。 -f 文件存在并且是常规文件,则为真(TRUE)。 -g 文件存在并且有设置set-group-id位,则为真(TRUE)。 -h 文件存在并且是符号链接,则为真(TRUE)。 -k 文件存在并且设置了sticky,则为真(TRUE)。 -p 文件存在并且是命名管道(FIFO),则为真(TRUE)。 -r 文件存在并且权限是可以读的,则为真(TRUE)。 -s 文件存在并且大小大于0,则为真(TRUE)。 -t 文件存在并且文件描述符fd已打开并指向终端,则为真(TRUE)。 -u 文件存在并且设置了set-user-id位,则为真(TRUE)。 -w 文件存在并且权限是可以写的,则为真(TRUE)。 -x 文件存在并且权限是可执行的,则为真(TRUE)。 -G 文件存在并且拥有者是有效的组ID,则为真(TRUE)。 -L 文件存在并且是符号链接,则为真(TRUE)。 -N 文件存在并且自上次读取以来已被修改,则为真(TRUE)。 -O 文件存在并且拥有者是有效的用户ID,则为真(TRUE)。 -S 文件存在并且是套接字,则为真(TRUE)。 file1 -ef file2 文件1和文件2引用相同的设备和inode编号,则为真(TRUE)。 file1 -nt file2 文件1比文件2新(根据修改日期),或者文件1存在而文件2不存在,则为真(TRUE)。 file1 -ot file2 文件1比文件2旧(根据修改日期),或者文件2存在而文件1不存在,则为真(TRUE)。 整数变量表达式 if [ int1 -eq int2 ] 如果int1等于int2 if [ int1 -ne int2 ] 如果不等于 if [ int1 -ge int2 ] 如果>= if [ int1 -gt int2 ] 如果> if [ int1 -le int2 ] 如果<= if [ int1 -lt int2 ] 如果< 字符串变量表达式 If [ $a = $b ] 如果string1等于string2 字符串允许使用赋值号做等号 if [ $string1 != $string2 ] 如果string1不等于string2 if [ -n $string ] 如果string 非空(非0),返回0(true) if [ -z $string ] 如果string 为空 if [ $sting ] 如果string 非空,返回0 (和-n类似) 进行字符串比较时,最好用双中括号,因为有时候采用单个中括号会产生错误。 注意,双中括号是Bash的一个扩展特性。如果出于性能考虑,使用ash或dash来运行脚本,那么将无法使用该特性。 测试两个字符串是否相同。 ● [[ $str1 = $str2 ]]:当str1等于str2时,返回真。也就是说, str1和str2包 含的文本是一模一样的。 ● [[ $str1 == $str2 ]]:这是检查字符串是否相同的另一种写法。 测试两个字符串是否不同。 ● [[ $str1 != $str2 ]]:如果str1和str2不相同,则返回真。 找出在字母表中靠后的字符串。 字符串是依据字符的ASCII值进行比较的。例如, A的值是0x41, a的值是0x61。因此, A 小于a, AAa小于Aaa。 ● [[ $str1 > $str2 ]]:如果str1的字母序比str2大,则返回真。 ● [[ $str1 < $str2 ]]:如果str1的字母序比str2小,则返回真。 测试空串。 ● [[ -z $str1 ]]:如果str1为空串,则返回真。 ● [[ -n $str1 ]]:如果str1不为空串,则返回真。 使用逻辑运算符 && 和 || 能够很容易地将多个条件组合起来: if [[ -n $str1 ]] && [[ -z $str2 ]] ; then commands; fi 例如: str1="Not empty " str2="" if [[ -n $str1 ]] && [[ -z $str2 ]]; then echo str1 is nonempty and str2 is empty string. fi
命令的逻辑关系:
在linux 中 命令执行状态:0 为真,其他为假
逻辑与: && -a
第一个条件为假时,第二条件不用再判断,最终结果已经有;
第一个条件为真时,第二条件必须得判断;
逻辑或: ||
逻辑非: !
正则 =~
其中 ~ 其实是对后面的正则表达式表示匹配的意思,如果匹配就输出1, 不匹配就输出0
if [[ ${version} =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then log_info "latest version of node_exporter is v${version}" pigsty的脚本
--update 2022年2月28日21:56:32
if和else语句能够嵌套使用。 if的条件判断部分可能会变得很长,但可以用逻辑运算符将它变得简洁一些:
[ condition ] && action; # 如果condition为真,则执行action
[ condition ] || action; # 如果condition为假,则执行action
&&是逻辑与运算符, ||是逻辑或运算符。编写Bash脚本时,这是一个很有用
的技巧。
-a是逻辑与操作符, -o是逻辑或操作符
例如:查看fd 为0 1 2 3 6是否已被占用。
lsof -a -p $$ -d 0,1,2,3,6 $$ 当前进程的PID -p : PID -d : FD -a: 其他两个选项的结果执行布尔AND运算
test命令
test命令可以用来测试条件。用test可以避免使用过多的括号,增强代码的可读性。之前讲过的[]中的测试条件同样可以用于test命令。例如:
if [ $var -eq 0 ]; then echo "True"; fi
也可以写成:
if test $var -eq 0 ; then echo "True"; fi
注意, test是一个外部程序,需要衍生出对应的进程,而 [ 是Bash的一个内部函数,因此后者的执行效率更高。 test兼容于Bourne shell、 ash、 dash等。