用 java 重写 Perl 和 shell 脚本有意义吗?

Posted

技术标签:

【中文标题】用 java 重写 Perl 和 shell 脚本有意义吗?【英文标题】:Does it make sense to rewrite Perl and shell scripts in java? 【发布时间】:2010-10-03 19:36:58 【问题描述】:

我有一堆脚本——一些在 perl 中,一些在 bash 中——用于:

创建数据库(表、索引、 约束、视图) 解析电子表格并将数据加载到数据库中 获取有关一堆文件的信息并将其加载到 数据库。

这些脚本与一个用 java 编写的更大的应用程序结合使用,我的经理要求我用 java 重写这些脚本。他的理由是,如果全部使用一种语言,那么使用、移植、管理、理解和支持会更容易,而且太多的单独部分是设计问题。

我最初的反应是,这是个坏主意。脚本非常简洁和快速,脚本中的琐碎任务(例如使用正则表达式查找和替换无效值)在 java 中执行时会更加冗长并且很可能更慢。

脚本的一个缺点是,当它们在 Windows 上运行时,它们需要 cygwin 才能运行。因此,我想提出一个反对意见,即我将所有 bash 脚本移植到 perl,以便它们可以在没有 cygwin 的 Windows 上运行,并且我会花时间组织和记录这些脚本。

问题在于“直觉反应”类型的反应不足以说服我的经理。我来自 linux 背景,他来自 Windows,我们有一些经典的 linux 与 windows 在方法上的差异。

所以我有两个问题:

    我的“直觉反应”正确吗?对于数据库管理、电子表格解析和文件处理任务,Java 是否更慢、更冗长且更难维护? 如果第一个问题的答案是肯定的,那么陈述我的案例的最佳方式是什么?

编辑:感谢大家的见解。我想澄清一下:脚本不是隐藏在混淆脚本中的成熟应用程序。在大多数情况下,它们是手动完成的任务,我通过脚本自动完成,后来随着需求的发展进行了修饰。我使用脚本语言而不是 java 开始的原因是因为这些任务所以在脚本中更容易完成。例如,一个脚本运行一堆查询、格式化结果并将它们输出到文件中。你认为在 java 中需要多少 LOC 才能做到这一点?

【问题讨论】:

这里发生了什么? 【参考方案1】:

问题是,你的直觉反应可能是对的,但这并不意味着你的经理一定是错的——他可能有很好的理由希望这一切都在 java 中完成。尤其是,如果你在公共汽车下,找到一个懂 java、perl 和 bash 的替代者将比找一个懂 java 的人困难得多。这撇开了“它们只能在安装了 cygwin 的 PC 上运行”的问题。而且很可能,性能并没有您想象的那么大。

话虽如此,您最好的选择是花一点时间估计将它们全部移植到 java 所需的时间,以便他做出明智的决定。并且,当您使用它时,估计将 bash 脚本移植到 perl 记录它们需要多长时间。然后让他决定。记住 - 他不会像你那样把大部分时间都花在编码上,所以他可以做出一些决定是公平的。

如果他决定继续使用 java 选项,尽可能移植其中一个脚本,然后报告两个版本,如果你对 perl/bash 脚本的简洁性是正确的,你应该能够通过并排检查两个版本获得一些里程。

编辑: MCS,老实说,在我看来,这些脚本在 perl 和/或 bash 中而不是 java 中实现得更好,但这并不是重点——重点是你如何向你的经理证明这一点。如果你解决这个问题,你就同时解决了“直觉反应”问题(顺便说一句,这里有一个提示 - 开始将你的直觉反应称为“基于经验的判断”)和“陈述我的案例的最佳方式”问题。

现在,您必须意识到的第一件事是,您的经理(可能)不会走这条路来激怒您。他几乎肯定对这些剧本有真正的担忧。考虑到他们可能是真正的担忧(如果他们不是,那就没有必要再进一步了——如果他出于某种政治原因下定决心做这件事,那么无论如何你都不会改变他的想法什么,所以只要继续下去并将其添加到您的简历中)因此,如果您要去任何地方,您需要向他提供解决他的担忧的信息。如果你能做到这一点,那么你就成功了一半以上。

那么,他的担忧是什么?根据你的帖子,以及我的判断和经验 :-) 我会说他们是:

可维护性 就是这样,只是可维护性

我也猜他的担心是不是

性能

当然,我对最后一个可能是错的;在我工作的最后一个地方,我们遇到了与复制有关的 SQL Server 性能问题,它影响了企业提供客户支持的能力,所以性能是一个问题,所以我们解决了这个问题。但一般来说,性能并不像程序员想象的那么严重。如果他真的告诉你性能是一个问题,那么就把它考虑进去。但如果他没有提到它,那就忘了它 - 可能只有你认为这些脚本在 perl/bash 中的运行速度比它们可能在java 很重要。

所以,可维护性。这归结为回答“如果 MCS 落在公共汽车下,谁来维护这些脚本?”这个问题。和补充问题“这会给我(即你的经理)带来问题吗?” (顺便说一句:不要被整个公共汽车的事情挂断。“跌倒在公共汽车下”是各种风险的有用且外交的简写,例如“如果有人用我公司无法提供的薪水引诱他离开会发生什么匹配?”、“如果他决定移民到百慕大会怎样?”、“如果我想解雇他会怎样?”、“如果我想提拔他会怎样?”当然还有“如果只是因为某种未知的、可能与公共汽车有关的原因,他有一天不再上班了吗?”)

请记住,考虑和减轻这些风险是您经理的工作。

那么,该怎么做呢?

首先,演示这些脚本的实际可维护性。或者至少它们的可维护性如何。记录它们(在适当的文档中,而不是在代码中)。培训一个同事来维护它们(选择一个想要获得/提高他们的 perl 和 bash 技能的人,以及你的经理信任的人)。重构它们以使它们更具可读性(必要时牺牲性能和巧妙的脚本技巧)。如果您想继续使用 bash,请创建一个文档,提供安装 cygwin 和 bash 的分步说明。不管怎样,记录下安装 perl 和运行脚本的过程。

其次,选择其中一个脚本并将其移植到 java。随意选择最能展示 perl/bash 优于 java 的脚本,但尽你所能移植它。使用 java.util.regex 做同样聪明的事情在你的 perl 中。将其记录为记录其他内部 java 实用程序的标准。如果性能确实是一个因素,请测量其相对于 perl/bash 脚本的性能。

第三,在经历了那个练习之后,对自己诚实地对待它们的相对可维护性。问问你训练的那个人他的想法。如果您仍然认为 perl/bash 脚本或多或少与 java 版本一样可维护,请尽可能准确地估计将剩余脚本移植到 java 所涉及的工作(您现在可以非常准确地做到这一点,因为你实际上已经移植了一个)。然后将比较脚本、文档和估算(以及性能数据,如果合适的话)交给您的经理,并与他一起检查。提出您的反建议(a. 将它们保留在 perl 和 bash 中,但记录它们并培训一位同事,b. 将 bash 脚本移植到 perl,记录它们并培训一位同事)。

最后,让您的经理权衡所有信息并做出决定,并遵守他的决定。事实上,不要只是遵守他的决定,要接受他可能是对的事实。仅仅因为你比他更了解 perl/bash/java 并不意味着你一定比他更了解管理团队/部门。如果他的决定是坚持使用 perl/bash,或者移植到 perl,那就高兴吧!因为您不仅走上了自己的路,而且您的经理对您的评价也有所提高,并在此过程中学到了宝贵的一课。

【讨论】:

是的,这里的公交车命中率非常高。 是吗?我认为这 3 种语言的工作知识是几乎任何有用工作的先决条件。 明确的巴士事故因素,同意。在我的上一份工作中,我的任务是将我的 perl 移植到 vb6。不幸的是,我准确估计了 4000 小时(是编写 perl 所需时间的两倍,我几乎不间断地写了 2 年)。从来没有发生过,现在他们都恨我。哦,好吧。 仅仅因为你将它们移植到java,并不意味着你完全减少了总线命中因素。移植到 java 的 Bash 和 Perl 脚本可能需要大量的进程管理,这在 java 中并非微不足道(尤其是与 Bash 和 Perl 相比时)。也许这就是他们被编写脚本的原因?【参考方案2】:

这取决于。我发现 Java 中的文本处理可能占用 Perl 中的代码量的 8 或 9 倍。如果这些脚本需要紧密集成到应用程序中,那么我会同意你的经理的意见,但如果只有后台任务,我会考虑在 Windows 上使用 ActiveState 并在 Perl 中重写 bash 脚本。

【讨论】:

要在 Windows 上获得更精简的 CPAN 体验,请考虑使用 Strawberry Perl【参考方案3】:

我个人觉得db,文件管理用java更难做,但是一旦写出来可能更容易维护。

但这值得吗?如果它有效,请不要“修复”它。

就我个人而言,我不在乎 - 如果我有工作要做,我会与我的经理讨论利弊,如果她坚持,我会去做并获得报酬。不过,通常她会清醒过来,让我做更重要的工作。

【讨论】:

【参考方案4】:

我觉得你的第一反应是对的。一个论点是如果它有效,不要“修复”它。另一个论点是一个开发人员可以独立于所使用的语言编写几乎相同数量的 SLOC。如果您知道 Java 是如何冗长的,这听起来很奇怪,但是想想您必须多么仔细地设计您的 Java 代码才能使用 perl 特性(如闭包、动态生成代码、即时正则表达式等)获得相同的结果。而现在,当 Java 与 Perl 的 SLOC 比率与相同结果的比率超过 10:1 时。您必须阅读、理解和维护的每一行代码。 Java 更快。是的。对于某些人来说,Java 在数字运算和某种文本处理方面更快。 Perl 在正则表达式和其他一些文本处理方面速度更快,而且通常比 Java 更高效。如果与 SLOC 相比,Perl 的可维护性更差,但如果与特性相比,Perl 与 Java 相同或更好。如果 Perl 是使用最佳实践编写并保持编码风格,则在可维护性方面可以击败 Java,尤其是在用于短脚本时。

【讨论】:

【参考方案5】:

我当然同意,如果您使用一组大多数人都知道的工具,这对每个人来说都会更容易。但是,由于您同时拥有 Java 和 Perl 代码,我假设至少你们中的一些人都知道这两种代码,因此老实说,我不认为同时拥有 Java 和 Perl 代码有什么大问题。

如果 Perl 脚本按预期工作并且可以维护,我不会花时间用 Java 重写它们。在 Perl 中编写脚本比在 Java imo 中容易得多,所以除非你真的需要转换,否则我看不出重点。我宁愿把时间花在真正为你所做的事情增加价值的事情上。

您说脚本需要 cygwin 才能运行。我在 Unix/Linux 和 Windows 上都做了很多 Perl,除非你做很多特定的 Unix 东西,否则我的经验是脚本可以很容易地转换为在 ActiveState 这样的 Windows Perl 下运行。在您的情况下,这可能是一个选择。

【讨论】:

【参考方案6】:

根据我自己的经验(包括在一个系统中混合 Java 和 Perl),我建议如下:

1) “Java 速度较慢”不一定正确,但也无关紧要(即使正确),除非额外的运行时间会干扰某些时间关键型工作流程。

2) 长期可维护性是一个合理的问题。有例如不必以两种语言维护的单个 DAO 层可以从长远来看得到回报。您需要修改多少 Java 代码和当前脚本(两次)才能涵盖数据库中的重构?

3) 如果您确实偏爱轻量级表示法,但您的经理想要 Java,您是否可以在 Java 库(从前一点)与在 JVM 上运行的一种可互操作的类脚本语言结合起来妥协,并且可以共享您编写的标准库的使用,例如数据库访问?我正在考虑 JRuby-Groovy-Scala-Jython 范围内的一些东西。

【讨论】:

【参考方案7】:

总的来说,我理解您的经理希望尽量减少和标准化您环境中使用的不同语言/平台。

但是, 脚本语言比 Java 等语言更适合某些任务。如果你觉得你被要求重写的脚本就是这种情况,也许不是建议使用 Perl 作为这个特定任务的一次性语言,你可以建议采用 Perl(或其他脚本语言,如果你认为你会获得更好的支持)作为脚本任务的“支持”语言。

也就是说,根据您所说的“结合使用”(即不同位的紧密耦合程度)的含义,这些任务可能更适合写成 Java 库由应用程序的其余部分调用。

【讨论】:

【参考方案8】:

全部转换为Perl

您认为JavaRegexp 更慢的权利。 PerlRegexp 变体经历了许多变化,以确保它尽可能快。

BASH 转换为Perl 应该很容易完成,Perl 可以轻松完成您在BASH 中所做的事情。

通过删除BASH 文件,您也可以摆脱Cygwin。

【讨论】:

【参考方案9】:

他们应该重写吗?那要看。你的老板最有力的论据是应用程序的其余部分是用 Java 编写的,听起来这可能是组织的发展方向。减少组织必须支持的不同语言的数量实际上是一个非常明智的长期决定。我知道,我知道,正确的工具适合正确的工作,但从成本的角度来看,完全有可能让组织花费更多的钱来聘请既了解 PERL 又了解 JAVA 的人,而不仅仅是 Java。即使脚本很漂亮,它们仍然必须得到支持,这意味着他必须至少保留一个知道如何做到这一点的员工。这是他(和组织)在一天结束时必须担心的另一件事。

【讨论】:

【参考方案10】:

我明白你在说什么,但简洁明了并不总是可以维护的——有时冗长和明确的也是可以维护的。

此外,一旦全部使用 Java,您将更有可能获得 UI/控制台的感觉,这可能是一种改进。

如果你真的喜欢脚本语言的感觉,也许你可以反对 groovy。它的语法对于 Java 程序员来说非常容易上手,并且 100% 兼容 java(包括在 groovy 等中扩展 java 类),但它是一种脚本语言——与任何语言一样强大——具有所有功能且无需编译这意味着。

顺便说一句,Java 可以很好地处理正则表达式。

顺便说一句,如果您编写了所有这些脚本并且是唯一熟悉它们的人,那么您可能想开始四处寻找新工作。很抱歉,但要求您将“特殊小技巧”记录在案且可维护通常是他们在裁员之前才考虑的事情。

【讨论】:

Java reg ex:一个警告,它们的行为就好像它们以“^”开头并以“$”结尾,如果您正在寻找一个经常需要将“.*”添加到边缘模式 somewhere within 搜索的字符串,而不是“完整”匹配。【参考方案11】:

照你说的做:将你的 shell 转换为 Perl 并记录它

您提到的代码似乎不是应用程序的一部分,它似乎是“设置”代码或“维护”代码。作为一个答案通知,“一份工作=一种工具”:

对于您的应用,它是 Java, 用于打包您的应用,它是 ant、maven 或 make, 用于设置环境,填写数据库,从日志中生成报告,它是一种脚本语言(Perl、Python、shell)。

说服你的老板:

    http://en.wikipedia.org/wiki/Golden_hammer 从一种语言迁移到另一种语言是有风险的:您必须花费大量时间来检查回归错误 根据我的经验,一行 Perl = 20 行 Java(试试看:迁移一个 Perl 脚本)。所以代码库将乘以 20,而要维护的代码越多,就越让人头疼

    Perl 将其所有模块和文档保存在同一个地方 (cpan.org)。对于 Java,没有“参考点”。您将不得不在网上浪费时间在 java 电子表格解析器之间做出选择,学习使用它(希望文档没问题),并制作一些 java-cryptic-glue-code:

    SheetHolder = ParserFactory .newInstance(配置.asProperties()) .parse(SheetReader.asStream());

【讨论】:

【参考方案12】:

只有一点。在很多方面,他都有自己的观点,但是……

Perl(或 bash 脚本)是一种胶水语言。它是坚持系统并使它们更好地工作的最佳语言之一。 Perl 是一种完全解释的语言,它为运行时代码重写和更动态的编程风格提供了强大的功能。您可以将 perl 代码块作为数据传递,并修改它们直到您在字符串上调用“eval”。无论是否有嵌入 perl 的本机 java 功能,您都可以轻松地自己创建这样的嵌入,从而构建一个非常强大的系统。

您可能想向您的主管明确说明,如果您删除 perl,您将失去什么潜力。在我的上一份工作中,两个开发人员将 IronPython 添加到我们的“法律语言列表”中,以便我们可以实现库并轻松地将它们通过数据库传递给一个大规模的自动化项目,这个项目变成了一个非常简单、非常小的项目,用一堆 python 代码粘合并粘合到已编译的模块上。

总而言之,有时一百万行 Java 无法完成 10 行 Bash 脚本所做的事情。那是你想要使用它的时候。其余时间,你的老板是对的,只要你有时间去做。

【讨论】:

Perl 不是“完全解释的”。贝壳群岛Perl 被编译成操作树,然后由 VM 运行。 这完全是语义。它可以在后台转换为 pascal,使用调试扩展进行编译,然后运行时将任何错误转换回 perl。它仍然可以解释并可以利用 if 的好处。 这可能是语义上的,但它是真的。它就像(选择一个)编译或解释为 Java。除了 perl 的编译速度要快得多,因此每次运行时都重新编译它并不重要。【参考方案13】:

如果您建造棚屋并在 80-90% 的时间使用锤子,是否意味着您应该只使用锤子来建造棚屋?不,您对工作的每个部分都使用最合适的工具,就像您所做的一样!

近年来,IT 员工的平均技能/经验水平也有所提高。例如。这个SO Poll 表明中等 SO 程序员 30 多岁,拥有超过 10 年的经验。

您的老板可以毫无问题地招聘具有广泛技能和经验的程序员。

【讨论】:

【参考方案14】:

你考虑过蚂蚁吗?我不得不承认我从未尝试过,但一直想将我的脚本移植到 Ant。文件操作很简单,甚至还有创建 SQL 语句的任务。当然,如果您的脚本更像程序,即许多循环结构,那么这不是要走的路。只是一个建议。

【讨论】:

熟悉导致鄙视:我必须使用 Ant。它经常很糟糕。 Ant 不是 Make。【参考方案15】:

在过去的一个项目中,Perl 代码被移植到 Java,从而显着提高了速度。该公司主要有 Java 程序员,我们的工具 Eclipse、Ant、JUnit 和 Maven 不适合 Perl 开发。我在很多公司都看过 Perl 代码,但大多数时候它只是作为临时解决方案、快速修复、原型、演示等。重写是有意义的,但你应该逐案查看,有时时间或人力不允许。

【讨论】:

【参考方案16】:

请记住,Java 不是唯一的 JVM 语言 - 也许像 Groovy 或 Jython 这样的东西会是让每个人都满意的折衷方案。

【讨论】:

【参考方案17】:

“为了操作文件和移动东西,你需要操作系统在你身边”

在不了解正确上下文的情况下,请谨慎遵循此建议!

操作系统支持 man (2) 和 (3) 等编程 API 以及用户命令 man (1)。

例如,使用 Perl 脚本驱动一系列 man(1) 不会运行得那么快 作为 JVM 有效地发出 man(2) 或 man(3) 的序列。

考虑这个例子:

在我加入的公司,我发现他们有一个循环调用 Java 实用程序的 Perl 模块 - 这是 make/perl/java 混合构建装置的一部分。

从表面上看,让 perl 读取元数据并在 JVM 中执行/调用来完成繁重的工作(在 perl 循环中合并文件的专有形式)似乎是合理的。

这种多进程方法的开销(设置/拆卸)非常显着,在 Windows 操作系统下尤其糟糕。

必须解决性能问题。

团队通过“重用”java 程序来解决性能问题 将其托管在 servlet 中并创建协议以将命令从 perl 发送到 java servlet。现在,循环中的迭代 JVM 设置/拆卸减少了,每个人都很高兴,直到出现诸如超时问题之类的边缘用例,团队在混合中添加了睡眠。

这种文化鼓励工具团队使用 perl,服务团队使用 Java。 用 Java 替换 perl 并消除所有开销的最佳方法要么被所有人遗忘,要么政治力量影响了 rube-goldberg 解决方案......

使用 ANT 或 Maven 等 JVM 语言进行构建可以避免这一切。

再次警告 :-)

【讨论】:

【参考方案18】:

这已经是多年后的事了,但我刚刚通过一些 Perl 脚本转换了 bash 脚本。我将系统重写为 Java 应用程序,还添加了 Groovy。 Java 和 Groovy 可以很好地协同工作。

groovy 运行纯 java 代码。 我可以在 groovy 中访问和操作我所有的 java 对象/结构/数据。我调用 groovy 脚本来处理我正在运行的 java 程序中的数据。 groovy 有一些很好的简写语法。我可以很容易地打开一个文件并用一个衬垫写入它。 groovy 也有一些简短的正则表达式语法。 groovy 脚本文件是在运行时解释的,因此当我的 java 程序仍在运行时,我可以更改我的 groovy 脚本代码,下次调用文件时它会使用新代码。

【讨论】:

【参考方案19】:

我的“直觉反应”正确吗?是java吗 更慢、更冗长、更难 维护数据库管理, 电子表格解析和文件处理 任务?

没有。

您的经理似乎指派了错误的人来执行此操作。很明显,您不习惯编写 Java,而且您不应该这样做。为什么“java 端”的一位开发人员不帮助您?

【讨论】:

不,我很喜欢编写 java - 我编写了这些脚本支持的大部分 java 应用程序。而且团队中没有其他开发人员。 执行需要更长的时间吗?可能不会,就像作者说的那样。用java写会需要更长的时间吗?你打赌。为了操作文件和移动东西,您需要操作系统。【参考方案20】:

对我来说,这取决于 Perl 写得有多糟糕(我从未见过 Perl 写得“好”),以及你是否需要阅读 Perl。

Perl 通常是一种只写一次,永不阅读的语言。如果一切正常,并且您不太可能需要更改它,我会说不要碰它。

【讨论】:

如果 Perl 是 WORN,Java 是一种永远不会写完一次,读完就读的语言。这种程度的话语不是很聪明吗? 我曾经读过(甚至可能已经读过)Java 是一种“一次编写,到处调试”的语言 ;-) 如果您从未见过“写得很好”的 perl,也许您应该停止编写蹩脚的代码?或者停止与编写蹩脚代码的人闲逛?我目前正在向过去 3-4 年由 3 个不同的人(在不同的时间)编写的 perl 应用程序添加功能。而且它是小菜一碟,因为它写得非常好,易于理解和阅读代码。

以上是关于用 java 重写 Perl 和 shell 脚本有意义吗?的主要内容,如果未能解决你的问题,请参考以下文章

进入由 shell 脚本设置的 perl 程序环境变量

写个脚本使用perl或shell对比oracle表数据,急啊,高分悬赏!

perl/shell 脚本中存在语法错误时的 rpm 构建预防

求一段perl或者shell程序,用来计算一个文件中某段字符的长度有多长。

Redhat 中的 Perl 和 shell 脚本

安装脚本的 shell 脚本与 perl - perl 有多普遍?