linux中bash shell特殊变量详解

我们在bash中经常看到一些特殊的变量,我们罗列下

$0,$1,$$,$#,$@,$*,$?,$(),${},$(())和(())

接下来我们就来一一介绍下这些变量的意思

1.$0

$后面紧跟着数字,数字从0开始,0代表运行的脚本本身名称,1为第一个参数,2为第二个参数,依次类推

例如以下脚本,test.sh内容如下

#!/bin/bash
echo $0
echo $1

我们运行

./test.sh sulao

打印出

./test.sh
sulao

2.$#

传递给脚本或函数的参数个数,上述脚本添加一个

#!/bin/bash
echo $0
echo $1
echo $#

然后比上面多打印一行2

3.$* 
传递给脚本或函数的所有参数。

4.$@ 
传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同

参数被双引号包裹时$*会将参数作为一个整体输出,如果是$@还是作为N个参数输出

5.$? 
上个命令的退出状态,或函数的返回值

6.$$ 
当前Shell进程ID,对于 Shell 脚本,就是这些脚本所在的进程ID

7.$()

$()和``用法差不多,都是用来做命令替换,将命令赋值给一个变量,但是$()这个不是每个bash版本都可以进行使用

8.${}

${a}和$a用法一样,只是可以更精确界定变量名称范围,例如

$ab 和 ${a}b

用了${}能够更方便的看清变量名

9.$(())

$(())是用来做整数运算的

在 bash 中,$(( )) 的整数运算符号大致有这些:

+ - * / :分别为 "加、减、乘、除"。
% :余数运算
& | ^ !:分别为 "AND、OR、XOR、NOT" 运算

10.(())

单纯用 (( )) 也可重定义变量值

a=5; ((a++)) 可将 $a 重定义为 6
a=5; ((a--)) 则为 a=4
a=5; b=7; ((a < b)) 会得到 0 (true) 的返回值。

常见的用于 (( )) 的测试符号有如下这些:

<:小于 >:大于
<=:小于或等于 >=:大于或等于
==:等于
!=:不等于

扩展知识

$()和${}的其他用法

我们可以用 ${ } 分别替换获得不同的值:

我们定义一个变量

file=/dir1/dir2/dir3/my.file.txt

${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 . 及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 . 及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my

记忆的方法为:

# 是去掉左边(在鉴盘上 # 在 $ 之左边)
% 是去掉右边(在鉴盘上 % 在 $ 之右边)

单一符号是最小匹配﹔两个符号是最大匹配。

${file:0:5}:提取最左边的 5 个字节:/dir1
${file:5:5}:提取第 5 个字节右边的连续 5 个字节:/dir2

我们也可以对变量值里的字符串作替换:

${file/dir/path}:将第一个 dir 提换为 path:/
path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部 dir 提换为 path:/
path1/path2/path3/my.file.txt

利用 ${ } 还可针对不同的变量状态赋值(没设定、空值、非空值):

${file-my.file.txt} :假如 $file 没有设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理)
${file:-my.file.txt} :假如 $file 没有设定或为空值,则使用my.file.txt 作传回值。 (非空值时不作处理)
${file+my.file.txt} :假如 $file 设为空值或非空值,均使用my.file.txt作传回值。(没设定时不作处理)
${file:+my.file.txt} :若 $file 为非空值,则使用 my.file.txt 作传回值。(没设定及空值时不作处理)
${file=my.file.txt} :若 $file 没设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (空值及非空值时不作处理)
${file:=my.file.txt} :若$file没设定或为空值,则使用my.file.txt作传回值,同时将 $file 赋值为my.file.txt 。(非空值时不作处理)
${file?my.file.txt} :若 $file 没设定,则将 my.file.txt 输出至STDERR。 (空值及非空值时不作处理)
${file:?my.file.txt} :若 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值时不作处理)

以上的理解在于, 你一定要分清楚 unset 与 null 及 non-null 这三种赋值状态.

一般而言, : 与 null 有关, 若不带 : 的话, null 不受影响, 若带 : 则连null 也受影响.

还有哦,${#var} 可计算出变量值的长度:

${#file} 可得到 27

因为 /dir1/dir2/dir3/my.file.txt 刚好是 27 个字节...

另外还有一些变量赋值的一些技巧

${var}取变量原值,与$var一样
${var:=word}如果var为空或者未设定,返回word,且var=word
${var:+word}如果var有值,返回word,var不变
${var:-word}如果var为空或者未设定,返回word,var不变
${var:?word}如果变量var为空或者未设定,返回word并退出shell,word没有值则输出:parameter null or not set,用于检测var是否被正常赋值
${var:num}返回var中第num个字符到末尾的所有字符,正从左往右,负从右往左,有空格:${var: -2},没有空格:${var:1-3}或${var:(-2)}
${var:num1:num2}从var的第num1个位置开始,提取长度为num2的子串。num1是位置,num2是长度
${var/word1/word2}将var中第一个匹配到的word1替换为word2
${var//word1/word2}将var中所有word1替换为word2


内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/686.html