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

最佳答案

我想到了;这是 bash(一个在 POSIX 标准指定的基本集合之上添加了许多功能的 shell 程序)和 dash(一个最低限度的 POSIX shell)之间的一个小的语法差异。许多操作系统使用 bash 作为/bin/sh,但 Debian(和 Ubuntu)不久前切换到 dash。

语法上的区别在于,将标准输出和标准错误重定向到同一位置的速记 &> 是一个 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

关于linux - Shell-script 在 Ubuntu 中没有给出预期的输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49714983/

10-12 12:35
查看更多