java - 从字符串中删除 shell 控制和不可打印的字符(linux 输出)

标签 java linux parsing

在网络扫描应用程序中,我需要解析一些脚本的输出来获取一些信息,但问题是我在 linux shell 和 java 输出中没有得到相同的输出,让我来描述一下(这个例子是在我需要在工作中扫描的网站之一上使用 whatweb 完成,但每当我在 shell 中有彩色输出时,我也会遇到这个问题):

这是我从 linux 的输出中得到的(带有一些颜色):

http://www.ceris-ingenierie.com [200] Apache[2.2.9], Cookies[ca67a6ac78ebedd257fb0b4d64ce9388,jfcookie,jfcookie%5Blang%5D,lang], Country[EUROPEAN UNION][EU], HTTPServer[Fedora Linux][Apache/2.2.9 (Fedora)], IP[185.13.64.116], Joomla[1.5], Meta-Author[Administrator], MetaGenerator[Joomla! 1.5 - Open Source Content Management], PHP[5.2.6,], Plesk[Lin], Script[text/javascript], Title[Accueil  ], X-Powered-By[PHP/5.2.6, PleskLin]

这是我从 Java 得到的:

[1m[34mhttp://www.ceris-ingenierie.com[0m [200] [1m[37mApache[0m[[1m[32m2.2.9[0m], [1m[37mCookies[0m[[1m[33mca67a6ac78ebedd257fb0b4d64ce9388,jfcookie,jfcookie%5Blang%5D,lang[0m], [1m[37mCountry[0m[[1m[33mEUROPEAN UNION[0m][[1m[35mEU[0m], [1m[37mHTTPServer[0m[[1m[31mFedora Linux[0m][[1m[36mApache/2.2.9 (Fedora)[0m], [1m[37mIP[0m[[1m[33m185.13.64.116[0m], [1m[37mJoomla[0m[[1m[32m1.5[0m], [1m[37mMeta-Author[0m[[1m[33mAdministrator[0m], [1m[37mMetaGenerator[0m[[1m[33mJoomla! 1.5 - Open Source Content Management[0m], [1m[37mPHP[0m[[1m[32m5.2.6,[0m], [1m[37mPlesk[0m[[1m[33mLin[0m], [1m[37mScript[0m[[1m[33mtext/javascript[0m], [1m[37mTitle[0m[[32mAccueil [0m], [1m[37mX-Powered-By[0m[[1m[33mPHP/5.2.6, PleskLin[0m]

我的猜测是,linux shell 中的颜色是由那些未知字符生成的,但在 java 中解析它们确实很痛苦。

我通过在新线程中运行脚本并执行 raw_data+=data;(其中 raw_data 是字符串)每当我的输出中有新行时获得此输出,最终将 raw_data 发送到我的解析器。

我怎样才能避免得到那些恼人的字符,从而获得更友好的输出,就像我在 linux 的 shell 中得到的一样?

最佳答案

在您执行 shell 脚本 的 Java 代码中,您可以添加一个额外的 sed 过滤器来过滤掉 shell 控制字符。

# filter out shell control characters
./my_script | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"

使用 tr -dc '[[:print:]]' 删除不可打印的字符,如下所示:

# filter out shell control characters
./my_script | \
 sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | \
 tr -dc '[[:print:]]'

您甚至可以在原始脚本周围添加一个包装器脚本来执行此操作。并调用包装器脚本。这使您可以在将其输入 Java 程序之前进行任何其他预处理,并保持它没有所有不必要的代码,您可以专注于应用程序的核心逻辑。

如果您出于任何原因无法添加包装器脚本并希望在 Java 中添加过滤器,Java 不支持直接在命令中使用管道。你必须像这样调用你的命令作为 bash 的参数:

String[] cmd = {
"/bin/sh",
"-c",
"./my_script | sed -r 's/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g'"
};

Process p = Runtime.getRuntime().exec(cmd);

在 Java 中使用正则表达式时,不要忘记转义所有 '\'

sed 过滤器的来源和描述:http://www.commandlinefu.com/commands/view/3584/remove-color-codes-special-characters-with-sed

关于java - 从字符串中删除 shell 控制和不可打印的字符(linux 输出),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28062897/

相关文章:

java - 如何使用xy坐标从SQLite数据库获取数据?

java - 如何获取文档的另一个嵌套列表的嵌套记录?

parsing - Jsoup 与 GWT(制作兼容的 JAR)

java - 解析后完成对象

java - quickfix/field/HaltReason 不可分配给 'quickfix/IntField

java - 加密后如何解密?

c++ - 是否有一个库可以在 C++ 中创建一组具有相同名称和索引的目录?

linux - 如何使用透明代理设置squid_session

regex - 仅当匹配 X 时,才使用 sed 从字符串中删除前 N 个和最后 N 个字符

JavaScript 无法解析 JSON