英文:
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:
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命令将javac
的stdout
和stderr
都发送到屏幕和文件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>&1
将stderr
指向了stdout
当前指向的位置,即屏幕。随后的>| mk.out
然后将stdout
(仅是stdout
)指向了mk.out
。不幸的是,这意味着stderr
仍然会显示在屏幕上。结果,mk.out
是空的(糟糕)。
在选项(2)中,stdout
首先被定向到mk.out
。随后的2>&1
将stderr
指向了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
当前指向的位置,但仅在所有重定向完成后才会发生。在管道中,这意味着javac
的stdout
被定向到tee
的stdin
,然后才将javac
的stderr
定向到javac
的stdout
的目标,即tee
的stdin
。
供参考:初始解决方案(javac
的Xstdout选项)
我发现我的javac
有一个特定用途的命令行选项-Xstdout OutputFileName.txt
。
不幸的是,我在线找到的并非所有javac
文档都显示了这个选项的可用性。在这种情况下,我找到的最直接的解决方案是在Vim中使用:term cat The/Output/File.Path
。
该页面还显示了许多Vim的替代方法,以及这里。
以后如果需要,以下是我发现相关的三个详细页面:
- https://superuser.com/questions/380772/removing-ansi-color-codes-from-text-stream
- https://unix.stackexchange.com/questions/14684/removing-control-chars-including-console-codes-colours-from-script-output
- https://unix.stackexchange.com/questions/4527/program-that-passes-stdin-to-stdout-with-color-codes-stripped
其中提到了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
. For option (1), I thought
2>&1stderr
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
in Vim.
cat The/Output/File.Path
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:
- https://superuser.com/questions/380772/removing-ansi-color-codes-from-text-stream
- https://unix.stackexchange.com/questions/14684/removing-control-chars-including-console-codes-colours-from-script-output
- https://unix.stackexchange.com/questions/4527/program-that-passes-stdin-to-stdout-with-color-codes-stripped
Mention is made of ansi2txt
, but you need Ubuntu for that.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论