Linux Shell脚本在Ubuntu中没有给出预期的输出

Linux Shell脚本在Ubuntu中没有给出预期的输出,linux,bash,unix,grep,Linux,Bash,Unix,Grep,Shell脚本: #!/bin/sh # -*-sh-*- java -classpath Test.jar Test test1.xml > javaOutput 2>&1; if cat javaOutput | tr '\n' ' ' | grep ".*java.lang.IndexOutOfBoundsException0.*ArrayList.java:653.*Test.java:142.*" &>/dev/null; then echo

Shell脚本:

#!/bin/sh
# -*-sh-*-
java -classpath Test.jar Test test1.xml > javaOutput 2>&1;
if cat javaOutput | tr '\n' ' ' | grep ".*java.lang.IndexOutOfBoundsException0.*ArrayList.java:653.*Test.java:142.*" &>/dev/null; then
    echo TRUE;
else
    echo FALSE;
fi
输出文件内容(javaOutput):

我正在使用以下版本的ubuntu:

Distributor ID: Ubuntu
Description:    Ubuntu 17.04
Release:    17.04
当我在命令提示符下复制并粘贴脚本时,它工作正常,并按预期回显FALSE,但每当我执行脚本时,它都会保持回显TRUE。我甚至在MacOs中运行了这个脚本,它在MacOs中按预期执行。我很困惑。如有任何帮助或见解,将不胜感激


注意:这里的期望值为FALSE,因为输出内容中没有字符串
IndexOutOfBoundsException0
;bash(一个shell程序,在POSIX标准指定的基本集合之上添加了许多特性)和dash(一个最小的POSIX shell)之间的语法差别很小。许多操作系统使用bash作为/bin/sh,但Debian(和Ubuntu)不久前改用了dash

语法上的区别在于,将标准输出和标准错误重定向到同一位置的速记
&>
是bash扩展;dash将把它解析为两个独立的标记,一个是
&
(一个命令分隔符,表示在后台运行命令),另一个是
(标准输出的重定向)。由于
&
标志着一个命令的结束和另一个命令的开始,重定向不适用于前面的命令,它本身就是一个最小的命令。本质上,dash将
if
then
之间的事物解析为:

cat javaOutput | tr '\n' ' ' | grep ".*java.lang.IndexOutOfBoundsException0.*ArrayList.java:653.*Test.java:142.*" &
>/dev/null
…和
如果
只查看该块中最后一个命令的成功/失败,这只是一个重定向。。。这总是成功的

幸运的是,解决方案很简单:不要使用bash速记,使用完整的
2>&1
重定向stdout和stderr:

if cat javaOutput | tr '\n' ' ' | grep ".*java.lang.IndexOutOfBoundsException0.*ArrayList.java:653.*Test.java:142.*" >/dev/null 2>&1; then

如果从脚本中删除
&>/dev/null
,它会打印什么?此外,Ubuntu的最新版本使用dash作为/bin/sh(而不是更常见的bash)。我看不出dash会与bash有什么不同,但请尝试将shebang设置为
#/bin/bash
并查看是否切换行为。@GordonDavisson调用正确。我删除了&>/dev/null,它开始工作了,但是对于与之相呼应的情况,它现在正在打印grep的输出。脚本的要求是在其计算结果为true时不生成输出。你知道有没有其他方法可以达到这个目的吗?我刚刚意识到为什么它不起作用。回答即将到来…另一个可能感兴趣的问题:非常感谢。它工作得很好。很高兴知道真正的根本原因。
if cat javaOutput | tr '\n' ' ' | grep ".*java.lang.IndexOutOfBoundsException0.*ArrayList.java:653.*Test.java:142.*" >/dev/null 2>&1; then