清理Windows上Vim的javac输出,可以通过Unix(Cygwin)工具进行处理。

huangapple go评论89阅读模式
英文:

Clean javac output on Windows for Vim, maybe via Unix (Cygwin) tools

问题

我是Java的新手,在Windows 10上安装了以下JDK:

C:\Program Files\AdoptOpenJDK\jdk-11.0.8.10-openj9

我可以从Cygwin的Bash命令行(在x终端中)调用编译器javac,但它会产生许多错误,似乎既不会输出到stdout也不会输出到stderr 我需要将这些错误信息发送到一个文件中,以便我可以用Vim查看。

以下是我的调用命令:

# mk.bash
# -------
javac \
-classpath "/c/Program Files/.../cplex.jar" \
TestSetup.java

这里的classpath参数在这里不相关,因为我只想专注于以Vim可查看的方式捕获javac的输出。

执行./mk.bash >| mk.out会生成一个空的

英文:

I am new to Java, and installed the following JDK on Windows 10:

C:\Program Files\AdoptOpenJDK\jdk-11.0.8.10-openj9

I can invoke the compiler javac from Cygwin's Bash command line
(in an x-terminal), but it creates many errors that seem to go to
neither stdout or stderr.
I need to send them to a file
that I can peruse with Vim.

Here is my invocation command

# mk.bash
# -------
javac \
-classpath "/c/Program Files/.../cplex.jar" \
TestSetup.java

The classpath argument is irrelevant here, as I
only want to focus on capturing javac's output in a Vim-perusable
way.

Issuing ./mk.bash >| mk.out generates an empty mk.out, as does
./mk.bash 2>&1 >| mk.out. I've used the latter pattern for decades
to redirect stderr to stdout and overwrite the destination file.

I can use the script command to send the javac output to mk.out:

script mk.out
./mk.bash
exit

I can then browse the error messages using Vim. However, the
contents are obfuscated by many binary characters (image & link to file below). Normally, I can
clean up messy files with dos2unix, but on this output, it quits due
to binary characters.

As another way to clean up the non-text content, Vim has a
fileformat=dos option which can be entered using :e ++ff=dos %.
The e and % says to edit the current file, while ++ff=dos says
to interpret the file as dos format (ff is fileformat). All
this does is clean up visual artifacts due to the different line
endings in Unix and DOS. All the error messages are still interspersed
with what seem like Escape characters ^[.

Is there any way to get javac to generate only plain text
output or to clean up the output?

Here is an image of the non-plain-text file in Vim:

清理Windows上Vim的javac输出,可以通过Unix(Cygwin)工具进行处理。

I doubt it is all that relevant, but I'm following this webpage to
compile a simple Java app TestSetup.java that invokes a 3rd party
tool: https://kunlei.github.io/cplex/cplex-java-setup.

答案1

得分: 0

底线

以下的Bash命令将javacstdoutstderr都发送到屏幕和文件mk.out

javac -classpath /Some/NonExistent/Jar/File.jar TestSetup.java \
2>&1 | tee mk.out

发现过程

我发现问题主要出在Bash的管道、重定向以及script命令的使用上。后者负责ANSI代码。之前我无法确定这一点,因为在没有script的情况下无法捕获javac的错误消息到文件中。所以我首先解决了这个问题,然后比较了使用script和不使用script的情况。以下是我的发现。

以下Bash命令创建一个不带ANSI代码的DOS格式文件:

javac -classpath '/Some/NonExistent/File.jar' TestSetup.java \
>| mk.out 2>&1

之前,我使用了**(1)** 2>&1 >| mk.out 而不是**(2)** >| mk.out 2>&1。对于选项(1),我认为stderr变成了指向stdout,所以我只需要将stdout指向mk.out

但实际情况并非如此。在选项(1)中,规范2>&1stderr指向了stdout当前指向的位置,即屏幕。随后的>| mk.out然后将stdoutstdout)指向了mk.out。不幸的是,这意味着stderr仍然会显示在屏幕上。结果,mk.out是空的(糟糕)。

在选项(2)中,stdout首先被定向到mk.out。随后的2>&1stderr指向了stdout指向的位置,也就是mk.out。因此,javac的错误消息被发送到了mk.out中。它没有包含ANSI代码,这是好事。

虽然选项(2)有效,但不是理想的;错误消息不会显示在屏幕上。这就是我回退到script的地方,发现它引入了ANSI代码:

script \
-c "javac -classpath '/Some/NonExistent/File.jar' TestSetup.java" \
mk.out

由于上面的方法解决了重定向stderr的问题,我寻找了避免使用script的Bash选项。以下的方法将stderr同时发送到屏幕和mk.out

javac -classpath /Some/NonExistent/Jar/File.jar TestSetup.java \
2>&1 | tee mk.out

根据上面选项(1)的解释,它似乎不应该起作用,但是Bash在用于管道时有个例外。具体来说,stderr被重定向到stdout当前指向的位置,但仅在所有重定向完成后才会发生。在管道中,这意味着javacstdout被定向到teestdin,然后才将javacstderr定向到javacstdout的目标,即teestdin

供参考:初始解决方案(javacXstdout选项)

我发现我的javac有一个特定用途的命令行选项-Xstdout OutputFileName.txt

不幸的是,我在线找到的并非所有javac文档都显示了这个选项的可用性。在这种情况下,我找到的最直接的解决方案是在Vim中使用:term cat The/Output/File.Path

该页面还显示了许多Vim的替代方法,以及这里

以后如果需要,以下是我发现相关的三个详细页面:

其中提到了ansi2txt,但需要Ubuntu才能使用。

英文:

Bottom line up front

The following Bash command sends both stdout and stderr from
javac to both the screen and the file mk.out:

javac -classpath /Some/NonExistent/Jar/File.jar TestSetup.java \
2>&1 | tee mk.out

How it was found

I found that the problem was primarily the use of Bash piping,
redirection, and the script command. The latter is responsible for
the ANSI codes. I could not determine this previously because I could
not capture the javac error messages in a file without script. So
I first solved that problem, then compared the use of script with
the absence of script. Here is what I found.

The following bash command creates a DOS format file without the ANSI
codes:

javac -classpath '/Some/NonExistent/File.jar' TestSetup.java \
>| mk.out 2>&1

Before, I had: (1) 2>&1 >| mk.out instead of (2) >| mk.out
2>&1
. For option (1), I thought stderr became directed to
stdout, so I simply needed to direct stdout to mk.out.

But that's not how it works. In option (1), the specification 2>&1
directs stderr to what stdout is currently directed at, i.e., the
screen. The subsequent >| mk.out then directs stdout (and only
std.out) to mk.out. Unfortunately, this meant that stderr was
still going to the screen. Presto, mk.out is left empty (bad).

In option (2), stdout is first directed to mk.out. The subsequent
2>&1 then directs stderr to what stdout is directed to, i.e.,
mk.out. Hence, the javac error messages get sent to mk.out.
It did not contain ANSI codes, which is good.

While option (2) works, it is not ideal; the error messages are not
shown on the screen. This is where I fell back to script and found
that it introduced the ANSI codes:

script \
-c "javac -classpath '/Some/NonExistent/File.jar' TestSetup.java" \
mk.out

Since the above solves the problem of redirecting stderr, I looked
for bash options that avoid script. The following sends stderr to
the screen and to mk.out:

javac -classpath /Some/NonExistent/Jar/File.jar TestSetup.java \
2>&1 | tee mk.out

According to the explanation of option (1) above, it looks like it
shouldn't work, but Bash makes an exception when it is used in a
pipeline. Specifically, stderr is redirected to what stdout is
directed to, but only after all redirections. In a pipeline, the
above means that javac's stdout is directed to tee's stdin,
and only then is javac's stderr directed to the target of
javac's stdout, i.e., tee's stdin.

For reference: Initial solution (javac's Xstdout option)

I found that my javac has a command line option -Xstdout OutputFileName.txt specifically for this purpose.

Unfortunately, not all javac documentation that I found online shows availability of this option. In that case, the most direct solution I found was :term
cat The/Output/File.Path
in Vim.

Many vim alternatives are also shown on that page, as well as here

For future reference, if needed, 3 fulsome pages that I found to be
relevant are:

Mention is made of ansi2txt, but you need Ubuntu for that.

huangapple
  • 本文由 发表于 2020年9月5日 23:19:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63755495.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定