Shell脚本不会在Ubuntu中提供预期的输出

时间:2018-04-08 06:09:08

标签: 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 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中运行这个脚本,它在MacOs中按预期执行。我很困惑。任何帮助或见解将不胜感激。

注意:此处的期望是获得FALSE,因为输出内容中没有字符串IndexOutOfBoundsException0

1 个答案:

答案 0 :(得分:3)

我明白了;它是bash(一个在POSIX标准指定的基本集之上添加了许多功能的shell程序)和破折号(一个最小的POSIX shell)之间的小语法差异。许多操作系统使用bash作为/ bin / sh,但是Debian(和Ubuntu)在一段时间内切换到了。

语法差异在于将标准输出和标准错误重定向到同一位置的简写&>是bash扩展名; dash会将其解析为两个单独的标记,&(一个命令分隔符,表示在后台运行命令),以及>(标准输出的重定向)。由于&标记一个命令的结束和另一个命令的开头,因此重定向不适用于前面的命令,它是自己的最小命令。从本质上讲,dash是将ifthen之间的事物解析为:

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

...而if仅查看该块中最后一个命令的成功/失败,这只是一个重定向...总是成功。

幸运的是,解决方案很简单:不要使用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