【问题标题】:Teaching assistant bash script to automate the process of finding, compiling, and running .java files助教 bash 脚本自动查找、编译和运行 .java 文件的过程
【发布时间】:2019-02-22 00:25:45
【问题描述】:

背景:

我在https://unix.stackexchange.com/questions/469680/teaching-assistant-bash-script-to-automate-the-process-of-finding-compiling-an 上发布了一个问题,并收到了一些非常好的建议。现在我想把我的过程更进一步。

设计概要:

我是一名大学助教,希望自动测试我学生的 Java 代码。我也在利用这个机会来提高我的 bash 技能,因为我觉得他们可以做得更好。我当前的 bash 脚本如下所示:

#!/bin/bash

list='/Users/ajm/Desktop/170Grading/output/list.txt'
score='/Users/ajm/Desktop/170Grading/output/score.txt'

> "$list"
> "$score"

find "$1" -name '*.java' >> "$list"

exec 3< "$list"

while IFS='' read -r -u 3 line || [ -n "$line" ]
do

    read -p "> $line (Press Enter to continue)"

    echo "the next file is $line" >> "$score"

    open -a "Xcode" "$line" 

    javac -d "/Users/ajm/Desktop/170Grading/runs" "$line" >> class && echo compiled >> "$score" || echo not compiled >> "$score"

    echo "standard in string" | cd "/Users/ajm/Desktop/170Grading/runs" java "$class" >> "$score"
done

争论点

目前,一切正常,直到完成前的最后一行。出于某种奇怪的原因,java "$class" 的输出没有附加到 "$score"。任何指导将不胜感激。

其他目标

A) 我希望能够为我的脚本添加额外的参数,这样我就不需要为每个新任务继续编辑它。例如在:

find "$1" -name '*.java' >> "$list"

我希望能够将 '*.java' 替换为 'string.java'。我知道我可以将字符串作为 $2 作为脚本的命令 arg 获取,但 '$2.java' 似乎不是解决此问题的正确方法。举个例子:假设我只想看一个以 color.java 结尾的 .java 文件的子集,我想说

bash script.sh directory color

并让其执行任务。如果没有$2,代码应该默认为'*.java'

【问题讨论】:

  • 你好。我很高兴你很好地提出了你的问题。干得好!祝你好运。
  • 您能否进一步向我们解释一下,最后一行应该输出什么?如果可能,最好举个例子。
  • 请更正javac行中的错误class字和"$class"

标签: java bash automation


【解决方案1】:

我的解决方案:

在与我的教授交谈后,我找到了解决方案。我想说明新脚本,旧脚本存在哪些问题,以及我们为使其工作所做的更改:

#!/bin/bash

list=/Users/ajm/Desktop/170Grading/output/list.txt
score=/Users/ajm/Desktop/170Grading/output/score.txt
runs=/Users/ajm/Desktop/170Grading/runs

> "$list"
> "$score"

rm -r "$runs"/*

find "$1" -name "*$3.java" >> "$list"

exec 3< "$list"

while IFS='' read -r -u 3 line || [ -n "$line" ]
do

    read -p "> $line (Press Enter to continue)"

    echo "the next file is $line" >> "$score"

    open -a "Xcode" "$line" 

    javac -d "$runs" "$line" && echo compiled >> "$score" || echo not compiled >> "$score"

    class=$(basename "$line")
    class=${class%.java}

    cd "$runs"

    echo "$2" | java -cp "$runs" ${class} >> "$score"

done

解释:

list、score 和 runs 都是指我的计算机上的路径,将来,我想让这个解决方案更适用于任何计算机。行:

> "$list"
> "$score"

将这些路径重新初始化为空。为了将运行文件夹重新初始化为空,我们使用:

rm -r "$runs"/*

递归删除运行目录中的任何内容。一句话

注意:因为有星号,如果运行设置不当,可能会对您的计算机造成不可逆转的损坏。

到这里为止的代码都是一样的:

class=$(basename "$line")
class=${class%.java}

在这一步中,我们只抓取类目录中的最后一项,然后我们将名称中的.class部分去掉,因为运行:

java code.class

真的是在告诉 jvm 去做:

java code.class.class

所以我们会遇到错误。

在最后一步中,我们使用花括号而不是引号 {} 来引用文件名:

echo "$2" | java -cp "$runs" ${class} >> "$score"

除了在执行时分配 $2 和 $3 而不是在脚本运行时分配之外,代码是相同的。

我希望如果将来有人遇到这个问题,这个答案会有所帮助。我将为这种用法重构一个更通用的脚本,将来我可能会将其作为附录发布。

【讨论】:

    【解决方案2】:

    您没有执行 Java。你在做

     cd "/Users/ajm/Desktop/170Grading/runs" java "$class" >> "$score"
    

    cd 命令看到 3 个参数并忽略“java”和“$class”。

    试试吧:

    cd "/Users/ajm/Desktop/170Grading/runs"
    echo "standard in string" | java "$class" >> "$score"
    

    或者如果您的 CLASSPATH 环境变量不包含 . 作为路径之一,您可以显式设置类路径而不更改目录:

    echo "standard in string" | java -cp "/Users/ajm/Desktop/170Grading/runs" "$class" >> "$score"
    

    【讨论】:

    • 我已经修改了我的代码,现在我得到的只是 /Users/ajm/Desktop/170Grading/runs 中每个编译文件的“错误:无法找到或加载主类”,但是当我查看运行文件夹,我看到许多已编译的 .class 文件。如果我查看 score.txt,每个 javac 都显示已编译。
    • 我已更改为第二种情况并尝试过,但我仍然收到“错误:无法找到或加载主类”。
    猜你喜欢
    • 2020-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 2011-10-11
    相关资源
    最近更新 更多