将"test"的结果分配给变量

Bar*_*den 16 bash

我正在编写一个脚本,我需要在几个地方使用文件测试的输出,包括shell函数内部.我想将文件存在分配给shell变量,如下所示:file_exists=[ -f $myfile ].

为了确保我已经覆盖了我的基础,我首先触摸一个文件,并测试它的存在:

file='a'
touch $file
if [ -f $file ]
then
    echo "1 -- '$file' exists"
fi
Run Code Online (Sandbox Code Playgroud)

输出:

1 -- 'a' exists
Run Code Online (Sandbox Code Playgroud)

该文件已成功创建 - 没有惊喜,但至少我知道我没有处理任何权限问题或任何事情.

接下来我测试以确保我可以在变量中存储布尔表达式:

mytest=/bin/true

if $mytest
then
    echo "2 -- \$mytest is true"
fi
Run Code Online (Sandbox Code Playgroud)

输出:

2 -- $mytest is true
Run Code Online (Sandbox Code Playgroud)

所以,我已经掌握了一些基本覆盖-条件表达式应该发出相同的输出/bin/true/bin/false...但是这不是我所看到的:

mytest=[ -f $file ]
if $mytest
then
    echo "3 -- \$mytest is true [expect true]"
else
    echo "3 -- \$mytest is false [expect true]"
fi
Run Code Online (Sandbox Code Playgroud)

此操作失败,并显示以下错误:

-f: command not found
Run Code Online (Sandbox Code Playgroud)

如果我使用test -f $file而不是,我会收到相同的错误消息[ -f $file ].

如果我在前面放一个空格[,那么错误就会消失......

mytest= [ -f $file ]
if $mytest
then
    echo "4 -- \$mytest is true [expect true]"
else
    echo "4 -- \$mytest is false [expect true]"
fi
Run Code Online (Sandbox Code Playgroud)

输出似乎是正确的:

4 -- $mytest is true [expect true]
Run Code Online (Sandbox Code Playgroud)

...但是如果我删除文件,我应该得到相反的结果:

rm $file
mytest= [ -f $file ]
if $mytest
then
    echo "5 -- \$mytest is true [expect false]"
else
    echo "5 -- \$mytest is false [expect false]"
fi
Run Code Online (Sandbox Code Playgroud)

......而我不这样做:

5 -- $mytest is true [expect false]
Run Code Online (Sandbox Code Playgroud)

公平地说,我预计这个空间会弄乱真相价值:

mytest= /bin/false
if $mytest
then
    echo "6 -- \$mytest is true [expect false]"
else
    echo "6 -- \$mytest is false [expect false]"
fi
Run Code Online (Sandbox Code Playgroud)

输出:

6 -- $mytest is true [expect false]
Run Code Online (Sandbox Code Playgroud)

那么,如何将test内置输出存储在shell变量中呢?

Cha*_*ffy 32

正如其他人在此记载的那样,使用字符串"true"是一个红色的鲱鱼; 这不是在shell脚本中存储布尔值的合适方法,因为评估它意味着动态调用命令,而不是简单地使用脚本中硬编码的shell builtins检查存储的值.

相反,如果您确实必须存储退出状态,请将其作为数值执行:

[ -f "$file" ]               # run the test
result=$?                    # store the result

if (( result == 0 )); then   # 0 is success
  echo "success"
else                         # nonzero is failure
  echo "failure"
fi
Run Code Online (Sandbox Code Playgroud)

  • @Silwing,最大的优点是你不需要引用它来正确处理空字符串、疯狂的 IFS 值(包含数字)、其中包含空格的字符串等。 `[ "$x" -eq "$y ]` 也不存在那些问题,但是比较拗口。 (2认同)

tri*_*eee 7

你需要引用空格:

mytest='[ -f $file ]'
if $mytest; then echo yes; fi
Run Code Online (Sandbox Code Playgroud)

然而,这非常脆弱并且可能不安全.请参阅http://mywiki.wooledge.org/BashFAQ/050以获取详细讨论以及一些更好的方法来完成类似的事情.

如果要封装一段复杂的代码,通常可以使用函数:

mytest () { [ -f "$file" ]; }
if mytest; then echo yes; fi
Run Code Online (Sandbox Code Playgroud)

如果你想运行一次代码并存储它的结果,以便你以后可以检查它,我会改写它:

if [ -f "$file" ]; then
    mytest=true
else
    mytest=false
fi
if $mytest; then echo yes; fi
Run Code Online (Sandbox Code Playgroud)

  • ...鼓励人们将命令名存储在变量*中,然后执行该命令(不带引号,甚至是否)来运行测试?真? (2认同)