vieyahn2017 / shellv

shell command test and study
4 stars 1 forks source link

5.11 linux 下shell中if的-e,-d,-f的含义,还有-z -n #39

Closed vieyahn2017 closed 5 years ago

vieyahn2017 commented 5 years ago

linux 下shell中if的“-e,-d,-f”是什么意思 https://www.cnblogs.com/senior-engineer/p/6206329.html

vieyahn2017 commented 5 years ago

文件表达式

-e filename 如果 filename存在,则为真 -d filename 如果 filename为目录,则为真 -f filename 如果 filename为常规文件,则为真 -L filename 如果 filename为符号链接,则为真 -r filename 如果 filename可读,则为真 -w filename 如果 filename可写,则为真 -x filename 如果 filename可执行,则为真 -s filename 如果文件长度不为0,则为真 -h filename 如果文件是软链接,则为真 filename1 -nt filename2 如果 filename1比 filename2新,则为真。 filename1 -ot filename2 如果 filename1比 filename2旧,则为真。

vieyahn2017 commented 5 years ago

整数变量表达式

-eq 等于 -ne 不等于 -gt 大于 -ge 大于等于 -lt 小于 -le 小于等于

vieyahn2017 commented 5 years ago

字符串变量表达式

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类似)

逻辑非 ! 条件表达式的相反 if [ ! 表达式 ] if [ ! -d $num ] 如果不存在目录$num

逻辑与 –a 条件表达式的并列 if [ 表达式1 –a 表达式2 ]

逻辑或 -o 条件表达式的或 if [ 表达式1 –o 表达式2 ]

vieyahn2017 commented 5 years ago

-z -n

[ -z STRING ] “STRING” 的长度为零则为真。

[ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。

vieyahn2017 commented 5 years ago

shell脚本[] [[]] -n -z 的含义解析

https://blog.csdn.net/keep_lcm/article/details/80551435

应用场景分析:

1、在中括号中,判断变量的值, 加不加双引号的问题?

-z 判断 变量的值,是否为空; zero = 0

- 变量的值,为空,返回0,为true
- 变量的值,非空,返回1,为false
-n 判断变量的值,是否为空   name = 名字
- 变量的值,为空,返回1,为false
- 变量的值,非空,返回0,为true
pid="123"
[ -z "$pid" ]  单对中括号变量必须要加双引号
[[ -z $pid ]]   双对括号,变量不用加双引号

[ -n "$pid" ]  单对中括号,变量必须要加双引号
[[ -z  $pid ]]  双对中括号,变量不用加双引号

2、多个条件判断,[] 和 [[]] 的区别?

2.1:[[ ]] 双对中括号,是不能使用 -a 或者 -o的参数进行比较的;

&& 并且  || 或   -a 并且   -o 或者
[[  ]]   条件判断 &&  并且     ||  或

[[ 5 -lt 3 || 3 -gt 6 ]]    一个条件,满足,就成立  或者的关系 
[[ 5 -lt 3 || 3 -gt 6 ]]      一个条件满足,就成立  或者的关系 

[[ 5 -lt 3 ]]  ||   [[3 -gt 6 ]] 
[[ 5 -lt 3 ]]  ||   [[3 -gt 6 ]]       写在外面也可以

&&  必须两个条件同时满足,和上述一样,这里想说明的问题的是:

[[ 5 -lt 3]]  -o [[ 3 -gt 6 ]]                [[ 5 -lt 3 -o 3 -gt 6 ]]     
[[ 5 -lt 3 -a  3 -gt 6 ]]       [[ 5 -lt 3 -a 3 -gt 6 ]]     
-a 和 -o就不成立了,是因为,[[]]  双对中括号,不能使用 -o和 -a的参数
直接报错:

2.2 [ ] 可以使用 -a -o的参数,但是必须在 [ ] 中括号内,判断条件,例如:

[ 5 -lt 3  -o  3 -gt 2 ]     或者条件成立
[5 -lt 3 ] -o [ 3 -gt 2]    或者条件, 这个不成立,因为必须在中括号内判断

如果想在中括号外判断两个条件,必须用&& 和 || 比较

[5 -lt 3 ] ||  [ 3 -gt 2]  
[5 -gt 3 ] &&  [ 3 -gt 2]    成立

相对的,|| 和 && 不能在中括号内使用,只能在中括号外使用

3、当判断某个变量的值是否满足正则表达式的时候,必须使用[[ ]] 双对中括号

$ tel=13612345678

$ [[ $tel =~ [0-9]{11} ]]

$ echo $?
0

$ [ $tel =~ [0-9]{11} ]
bash: [: =~: binary operator expected

单对中括号,直接报错

vieyahn2017 commented 5 years ago

这有篇记录了现象,原因分析是错误的一篇文章

Shell 脚本中-z和-n的探讨

https://blog.csdn.net/u011259594/article/details/46402001

千里之行,始于足下。未来几年里希望这个博客能一直坚持写下去。

正文 在学习shell脚本时发现在做if判断时,对于空字符串的判断上-n做出了一些错误的判定,以下是测试过程,不愿细看的请直接跳转到文章最后看结果。

出错代码如下

a=""
if [ -z $a ]
then 
    echo "Length of a: \"$a\" is zero "
else 
    echo "Length of a: \"$a\" is not zero "
fi

if [ -n $a ]
then 
    echo "Length of a: \"$a\" is not zero "
else 
    echo "Length of a: \"$a\" is zero "
fi

输出:

Length of a: "" is zero 
Length of a: "" is not zero

显然答案是错误的。 
有趣的是,将$a两边加上引号变成 "$a" 后,结果却出乎意料的正确了。

a=""
if [ -z "$a" ]
then 
    echo "Length of a: \"$a\" is zero "
else 
    echo "Length of a: \"$a\" is not zero "
fi

if [ -n "$a" ]
then 
    echo "Length of a: \"$a\" is not zero "
else 
    echo "Length of a: \"$a\" is zero "
fi
```sh
输出:

Length of a: "" is zero 
Length of a: "" is zero

这次的输出是正确的。 
因此我们可以大胆猜测,可能是因为a=""时,编译器并未识别成字符串从而导致-n判断失误

通过查找shell的源码coreutils-8.23中的test.c发现
```c
switch (argv[pos][1])
{
    ...

    case 'n':           /* True if arg has some length. */
      unary_advance ();
      return argv[pos - 1][0] != 0;

    case 'z':           /* True if arg has no length. */
      unary_advance ();
      return argv[pos - 1][0] == '\0';

    ...
}

结论 -z的判断是通过判断字符串首位是否为\0来完成,而-n则变成了0,笔者猜测就是这个细微的差别造成了结果的不同。 在查阅所有相关源码之后,我并没找到更深层的原因,暂时只能给出解决办法。即: 在处理字符串时,-n参数是有bug的,若要判断a是否为空需要使用

if [ "$a+x" = "x" ]

将来如果有更多发现,将在本文下更新,也欢迎留言交流

Night_k的回帖 才是正解:

因为遇到了同样的错误,找到了您的这篇文章,不过参考其他的搜索结果,我的理解稍微有些不同, 参考:https://blog.csdn.net/ciky2011/article/details/37876119 , 在 if [ -n $a ] 这种情况,如果 $a 是空,实际是按照 if [ -n ] 来判断了,这种情况下,-n 成了作为判断的字符串,所以返回了 True, 类似的随便写一个字符串 if [ -tdsfadsfa ],是返回 True 的,使用加引号的方式,或者 if [[ -n $a ]] 可以避免这种情况(6个月前#1楼)