1. info expr
‘expr’支持模式匹配和字符串操作。字符串表达式的优先级高于数值表达式和逻辑关系表达式。
‘STRING : REGEX’
执行模式匹配。两端参数会转换为字符格式,且第二个参数被视为正则表达式(GNU基本正则),它默认会隐含前缀"^"。随后将第一个参数和正则模式做匹配。
如果匹配成功,且REGEX使用了’(‘和’)’,则此表达式返回匹配到的,如果未使用’(‘和’)’,则返回匹配的字符数。
如果匹配失败,如果REGEX中使用了’(‘和’)’,则此表达式返回空字符串,否则返回为0。
只有第一个’(…)‘会引用返回的值;其余的’(…)‘只在正则表达式分组时有意义。
在正则表达式中,’+’,’?‘和’|‘分表代表匹配一个或多个,0个或1个以及两端任选其一的意思。
‘match STRING REGEX’
等价于’STRING : REGEX’。
‘substr STRING POSITION LENGTH’
返回STRING字符串中从POSITION开始,长度最大为LENGTH的子串。如果POSITION或LENGTH为负数,0或非数值,则返回空字符串。
‘index STRING CHARSET’
CHARSET中任意单个字符在STRING中最前面的字符位置。如果在STRING中完全不存在CHARSET中的字符,则返回0。
‘length STRING’
返回STRING的字符长度。
‘+ TOKEN’
将TOKEN解析为普通字符串,即使TOKEN是像MATCH或操作符"/“一样的关键字。这使得’expr length + “
x
"
′
或
′
e
x
p
r
+
"
x"'或'expr + "
x"′或′expr+"x” : ‘.*/(.)’'可以正常被测试,即使”$x"的值可能是’/‘或’index’关键字。这个操作符是一个GUN扩展。
通用可移植版的应该使用’" KaTeX parse error: Can't use function '\(' in math mode at position 12: token" : ' \̲(̲.*\)''来代替'+ "token"’。
要让expr将关键字解析为普通的字符,必须使用引号包围。
'expr’支持普通的算术操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。
'+ -'加减运算。两端参数会转换为整数,如果转换失败则报错。
'* / %'乘,除,取模运算。两端参数会转换为整数,如果转换失败则报错。
'expr’支持普通的逻辑连接和逻辑关系。它的优先级最低。
‘|’ 如果第一个参数非空且非0,则返回第一个参数的值,否则返回第二个参数的值,但要求第二个参数的值也是非空或非0,否则返回0。如果第一个参数是非空或非0时,不会计算第二个参数。
经过测试,以上手册内容是错误的。正确的应该是:如果第一个参数非0,则返回第一个参数的值,否则返回第二个参数。但如果任意一个参数为空,则报错。除非空字符串使用引号包围,此时将和0的处理方式一样。
‘&’ 如果两个参数都非空且非0,则返回第一个参数,否则返回0。如果第一个参为0或为空,则不会计算第二个参数。
经过测试,以上手册内容是错误的。正确的应该是:如果两个参数都非0,则返回第一个参数,否则返回0。但任意一个参数为空,则报错。除非空字符串使用引号包围,此时将和0的处理方式一样。
'< <= = == != >= >‘比较两端的参数,如果为true,则返回1,否则返回0。"==“是”="的同义词。"expr"首先尝试将两端参数转换为整数,并做算术比较,如果转换失败,则按字符集排序规则做字符比较。
括号’()'可以改变优先级,但使用时需要使用反斜线对括号进行转义。
2.示例
2.1将shell中变量’foo’的值增加1
foo=$(expr $foo + 1)
2.2 输出变量路径变量’$fname’中不包含’/'的文件名部分
expr $fname : '.*/\(.*\)' '|' $fname
解释:其中的’|'是expr中的连接符,只不过是被引号包围防止被shell解析。例如
f
n
a
m
e
=
/
e
t
c
/
h
o
s
t
s
,
则
此
表
达
式
返
回
h
o
s
t
s
,
如
果
f
n
a
m
e
=
/
u
s
r
/
s
h
a
r
e
/
,
则
此
表
达
式
′
∣
′
的
左
边
为
空
,
所
以
返
回
′
∣
′
右
边
的
值
,
即
fname=/etc/hosts,则此表达式返回hosts,如果fname=/usr/share/,则此表达式'|'的左边为空,所以返回'|'右边的值,即
fname=/etc/hosts,则此表达式返回hosts,如果fname=/usr/share/,则此表达式′∣′的左边为空,所以返回′∣′右边的值,即fname,即返回/usr/share/。
An example showing that ‘+’ is an operator:
expr aaa : 'a\+' # 解释:因为REGEX部分没有使用\(\),所以返回匹配的字符数 3
expr abc : 'a\(.\)c' # 解释:因为REGEX部分使用了\(\),所以返回匹配的字符 b
expr index abcdef cz
3
expr index index a # 解释:因为第二个index是关键字
error-> expr: syntax error
expr index + index a # 解释:使用+将index关键字解析为普通字符串
0
数值表达式("+ - * / %")和比较表达式("< <= = == != >= >")会先将两端的参数转换为数值,转换失败将报错。所以可借此来判断参数或变量是否为整数。
expr中的很多符号需要转义或使用引号包围。
所有操作符的两边,都需要有空格。
2.3 string : REGEX
要输出匹配到的字符串结果,需要使用"(“和”)",否则返回的将是匹配到的字符串数量。
[root@master ~]# expr abcde : 'ab\(.*\)'
cde
[root@master ~]# expr abcde : 'ab\(.\)'
c
[root@master ~]# expr abcde : 'ab.*'
5
[root@master ~]# expr abcde : 'ab.'
3
[root@master ~]# expr abcde : '.*cd*'
4
#注意,由于REGEX中隐含了"^",所以使得匹配时都是从string首字符开始的。
[root@master ~]# expr abcde : 'cd.*'
0
之所以为0,是因为真正的正则表达式是"^cd.*",而abcde不是c开头而是a开头的,所以无法匹配到任何结果。因此,任何字符串匹配时,都应该从首字符开始。
字符串匹配时,会先将两端参数转换为字符格式。
2.4 index string chars
该表达式是从string中搜索chars中某个字符的位置,这个字符是string中最靠前的字符。
[root@master ~]# expr index abcde dec
3
该命令将对字符串"dec"逐字符分解,首先分解得到第一个字符d,从abcde中搜索到d的位置为4,再分解得到第二个字符e,该字符在abcde中的位置为5,最后得到的字符是c,该字符在abcde中的位置为3。其中3是最靠前的字符,所以命令返回的结果为3。
[root@master ~]# expr index abcde xdc
3
#如果chars中的所有字符都不存在于string中,则返回0。
[root@master ~]# expr index abcde 1
0
[root@master ~]# expr index abcde 1x
0
2.5 substr string pos len
该表达式是从string中取出从pos位置开始长度为len的子字符串。如果pos或len为非正整数时,将返回空字符串。
[root@master ~]# expr substr abcde 2 3
bcd
[root@master ~]# expr substr abcde 2 4
bcde
[root@master ~]# expr substr abcde 2 5
bcde
[root@master ~]# expr substr abcde 2 0
[root@master ~]# expr substr abcde 2 -1
2.6 length string
该表达式是返回string的长度,其中string不允许为空,否则将报错,所以可以用来判断变量是否为空。
[root@master ~]# expr length abcde
5
[root@master ~]# expr length 111
3
[root@master ~]# expr length $xxx
expr: syntax error
[root@master ~]# if [ $? -ne 0 ];then echo '$xxx is null';fi
$xxx is null
2.7 + token
expr中有些符号和关键字有特殊意义,如"match"、“index”、“length”,如果要让其成为字符,使用该表达式将任意token强制解析为普通字符串。
[root@master ~]# expr index index d
expr: syntax error
[root@master ~]# expr index length g
expr: syntax error
[root@master ~]# expr index + length g
4
#对值为关键字的变量来说,则无所谓。
[root@master ~]# len=lenght
[root@master ~]# expr index $len g
4
2.8 算术运算
[root@master ~]# expr 1 + 2
3
[root@master ~]# a=3
[root@master ~]# b=4
[root@master ~]# expr $a + $b
7
[root@master ~]# expr 4 + $a
7
[root@master ~]# expr $a - $b
-1
算术乘法符号"*"因为是shell的元字符,所以要转义,可以使用引号包围,或者使用反斜线。
[root@master ~]# expr $a * $b
expr: syntax error
[root@master ~]# expr $a '*' $b
12
[root@master ~]# expr $a \* $b
12
[root@master ~]# expr $b / $a # 除法只能取整数
1
[root@master ~]# expr $b % $a
1
任意操作符两端都需要有空格,否则:
[root@master ~]# expr 4+$a
4+3
[root@master ~]# expr 4 +$a
expr: syntax error
由于expr在进行算术运算时,首先会将操作符两边的参数转换为整数,任意一端转换失败都将会报错,所以可以用来判断参数或变量是否为整数。
[root@master ~]# expr $a + $c
expr: non-integer argument
[root@master ~]# if [ $? != 0 ];then echo '$a or $c is non-integer';fi
$a or $c is non-integer
2.9 比较操作符< <= = == != >= >
其中"<“和”>“是正则表达式正的锚定元字符,且”<"会被shell解析为重定向符号,所以需要转义或用引号包围。
这些操作符会首先会将两端的参数转换为数值,如果转换成功,则采用数值比较,如果转换失败,则按照字符集的排序规则进行字符大小比较。比较的结果若为true,则expr返回1,否则返回0。
[root@master ~]# a=3
[root@master ~]# expr $a = 1
0
[root@master ~]# expr $a = 3
1
[root@master ~]# expr $a \* 3 = 9
1
[root@master ~]# expr abc \> ab
1
[root@master ~]# expr akc \> ackd
1
2.10 逻辑连接符号"&“和”|"
这两个符号都需要转义,或使用引号包围。
以下是官方文档中给出的解释,但实际使用过程中是不完全正确的。
"&"表示如果两个参数同时满足非空且非0,则返回第一个参数的值,否则返回0。且如果发现第一个参数为空或0,则直接跳过第二个参数不做任何计算。
"|"表示如果第一个参数非空且非0,则返回第一个参数值,否则返回第二个参数值,但如果第二个参数为空或为0,则返回0。且如果发现第一个参数非空或非0,也将直接跳过第二个参数不做任何计算。
正确的应该是:
"&"表示如果两个参数都非0,则返回第一个参数,否则返回0。但任意一个参数为空,则expr报错。除非空字符串使用引号包围,则处理方法和0一样。
"|"表示如果第一个参数非0,则返回第一个参数的值,否则返回第二个参数。但如果任意一个参数为空,则expr报错。除非空字符串使用引号包围,则处理方法和0一样。
[root@master ~]# expr $abc '|' 1
expr: syntax error
[root@master ~]# expr "$abc" '|' 1
1
[root@master ~]# expr "$abc" '&' 1
0
[root@master ~]# expr $abc '&' 1
expr: syntax error
[root@master ~]# expr 0 '&' abc
0
[root@master ~]# expr abc '&' 0
0
[root@master ~]# expr abc '|' 0
abc
[root@master ~]# expr 0 '|' abc
abc
[root@master ~]# expr abc '&' cde
abc
[root@master ~]# expr abc '|' cde
abc
————Blueicex 2020/03/07 21:28 blueice1980@126.com