Shell编程中出现 `ambiguous redirect` 和 `binary operator expected` 错误的解决方法以及相关知识点

2024-08-08 13:46:07 浏览数 (1)

0 报错的背景

最近在学习《Linux命令行和shell脚本编程大全》(第四版)这本书,对于自己遇到的问题以及通过搜索引擎和书籍中的解决方案进行一个案例的剖析,希望对于像我这样的初学者,有一个帮助。

在第十二章结构化命令的test命令章节中字符串比较小节中,我自己的验证示例如下:

代码语言:shell复制
#!/bin/bash
param1=Full
param2=""
if [ $param1 > $param2 ]
then
        echo "$param1 大于 $param2"
fi

if [ -z $param2 ]
then
        echo "$param2 是空值"
else
        echo "$param2 非空"
fi

出现报错:

代码语言:shell复制
test1.sh: line 4: $param2: ambiguous redirect
1 如何解决ambiguous redirect

该报错的意思是:不明确的重定向,因为>或者<号在脚本中被视为了重定向,而$param2本身为空值,此处的重定向的语句就会被抛出ambiguous redirect错误。

书中直接将答案给出:“大于号和小于号必须转义,否则shell会将其视为重定向符,将字符串值当作文件名”,因此需要在大于号或者小于号前进行转义,如下:

代码语言:shell复制
#!/bin/bash
param1=Full
param2=""
if [ $param1 > $param2 ]
then
        echo "$param1 大于 $param2"
fi

if [ -z $param2 ]
then
        echo "$param2 是空值"
else
        echo "$param2 非空"
fi

发现又双报错

代码语言:shell复制
[root@iZuf6gxtsgxni1r88kx9rtZ gulu]# sh test1.sh 
test1.sh: line 4: [: Full: unary operator expected
2 如何解决 unary operator expected 报错

根据搜索引擎,发现unary operator expected报错的意思是一元运算符预期错误,其实这个字段的本身我们能猜到一点方向。但这里先卖个关子,讲一些相关的知识点。

2.1 '"的差异

这里直接引用别人的成果:

在shell脚本中,单引号(')和双引号(")都用于文本引用,但它们之间有一些区别:

双引号

  1. 当要引用一个变量的值时,一般推荐使用双引号。
  2. 使用双引号除了变量名前缀($)、后引符(`)和转义符()外,会使shell不再解释引号中其它所有的特殊字符。
  3. 用双引号时仍被当成特殊字符,允许引用一个被双引号引起的变量("仍被当成特殊字符,允许引用一个被双引号引起的变量("variable"), 那也是说$variable会被它的值所代替。
  4. 用双引号还能使句子不被分割开. 一个参数用双引号引起来能使它被看做一个单元,这样即使参数里面包含有空白字符也不会被shell分割开了。

单引号

  1. 单引号(' ')和双引号类似,但它不允许解释变量引用,因此,在单引号内的字符$的特殊意思无效了。在单引号内,除了字符',每个特殊字符都只是字面的意思。
  2. 单引号(全局引用)比双引号(部分引用)更严格的处理引用部分。

反引号

  1. 一般用于引用命令,执行的时候命令会被执行,相当于$(...)

无引号

  1. 把内容输出出来,但可能不会将含有空格的字符串视为一个整体输出,如果内容中有命令,变量等,会先把变量,命令解析结果,然后再输出最终内容来,如果字符串中带有空格等特殊字符,则不能完整的输出,需要改加双引号,一般连续的字符串,数字,路径等可以用,不过最好用双引号替代之。

总而言之,''相当于绝对引用,能用绝对引用除了'之外所有字符,也就是能保证引用内的全部字面意思;而"“相当于相对引用,对于变量,转义等,引用的是实际的值。

2.2 问题的解决思路

由于报错提示是说由于一元运算符预期的错误,那我们再会过来看看shell脚本。

param2="" param2用""来赋了一个空值,在变量引用的时候,使用了无引用,而跟上2.1的关于引用的知识点,容易想到,是否是由于无引用导致了空格的字符串的不完整输出,导致一元运算符运算失败呢?

所以,修改如下:

代码语言:shell复制
#!/bin/bash
param1=Full
param2=""
if [ "$param1" > "$param2" ]
then
        echo "$param1 大于 $param2"
fi

if [ -z $param2 ]
then
        echo "$param2 是空值"
else
        echo "$param2 非空"
fi

结果如下:

代码语言:shell复制
[root@iZuf6gxtsgxni1r88kx9rtZ gulu]# sh test1.sh 
$param1 大于 $param2
$param2 是空值

问题解决!

3 参考文献
  1. Shell-单引号和双引号的区别
  2. shell中定义变量用双引号和单引号以及不用引号的区别
  3. shell 中单引号,双引号,不加引号的区别

0 人点赞