Linux-Shell脚本在Ubuntu中无法提供预期的输出

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):

0,2,468.000000
1,2,305.000000
2,5,2702.000000
3,3,1672.000000
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
    at java.util.ArrayList.rangeCheck(ArrayList.java:653)
    at java.util.ArrayList.get(ArrayList.java:429)
    at Test.processPayments(Test.java:113)
    at Test.processFile(Test.java:131)
    at Test.main(Test.java:142)

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

Distributor ID: Ubuntu
Description:    Ubuntu 17.04
Release:    17.04

当我将脚本复制并粘贴到命令提示符中时,它可以正常工作并按预期方式回显FALSE,但是每当我执行脚本时,它都会一直回显TRUE.我什至在Mac OS中运行了该脚本,并且该脚本在MacO中按预期执行.我很困惑.任何帮助或见解将不胜感激.

注意:由于输出内容中没有字符串IndexOutOfBoundsException0,因此这里的期望是FALSE.

最佳答案
我想到了; bash(在POSIX标准指定的基本集之上添加了很多功能的shell程序)和dash(裸机POSIX shell)之间的语法差异很小.许多操作系统都将bash用作/ bin / sh,但是Debian(和Ubuntu)切换到前划线.

语法上的差异是速记&> bash扩展是将标准输出和标准错误都重定向到同一位置的方法;破折号会将其解析为两个单独的标记,即& (表示在后台运行命令的命令定界符),> (标准输出的重定向).自&标记一个命令的结束和另一个命令的开始,重定向不适用于前面的命令,这是它自己的一个最小命令.本质上,破折号将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

转载注明原文:Linux-Shell脚本在Ubuntu中无法提供预期的输出 - 代码日志