【问题标题】:Executing bash script, read its output and create html with Perl执行 bash 脚本,读取其输出并使用 Perl 创建 html
【发布时间】:2011-08-20 21:18:40
【问题描述】:

我有一个 bash 脚本,它产生不同的整数值。当我运行该脚本时,输出如下所示:

12

34

34

67

6

此脚本在 Solaris 服务器上运行。为了向网络中的其他用户提供这些值,我决定编写一个 Perl 脚本,它可以:

  • 运行 bash 文件
  • 读取其输出
  • 构建一个带有存储 bash 值的表的小型 html 页面

这对我来说是一项艰巨的工作,因为我几乎没有使用 Perl 的经验。我知道我可以使用 system 来执行 unix 命令(和 bash 文件),但我无法获得输出。我还听说过 qx,这听起来对我的案例非常有用。

但我必须承认我不知道如何开始......你能给我一些提示如何解决这个问题吗?

【问题讨论】:

    标签: perl bash


    【解决方案1】:

    这样的问题有点难以知道从哪里开始。

    您所指的qx 是Perl 的一个特性。 “q*”或“Quote and Quote-like Operators”记录在 Perl “operators”手册页中(通常您会使用 man perlop 在安装了 Perl 的系统上阅读)。

    具体来说,qx 是“命令的引用执行”...本质上是 Perl 中 `(反引号或“命令替换”)运算符的另一种形式。

    换句话说,如果你执行如下命令:

    perl -e '$foo = qx{ls};打印 "\n###\n$foo\n###\n";'

    ... 在安装了 Perl 的系统上,它应该运行 Perl,它应该评估 (-e) 您提供的表达式(引用)。换句话说,我们正在命令行上编写一个小程序。这个程序首先创建一个变量,其内容将是一个“标量”(这是字符串或数字的 Perl 术语)。我们将通过执行ls 命令捕获的输出(= 或赋值运算符)分配回此变量($foo)。之后,我们将打印变量的内容(无论ls 命令会打印什么),并在这些内容之前和之后加上### 行。

    Perl 的qx 运算符(以及其他各种 q* 运算符)的一个怪癖是它允许您使用几乎任何您喜欢的字符来分隔命令。例如perl -e '$bar = qx/pwd/;' 将捕获pwd 命令的输出。当您使用通常用作文本括号、大括号、方括号等的分隔符的任何字符时,qx 命令将查找适当的匹配分隔符。如果您使用任何其他标点符号(或非字母数字字符?),那么相同的字符也将是终止分隔符。这种后来的行为类似于旧的sed 实用程序和ed 行编辑器的“替换”命令中的一个特性,并受到其启发;而括号、大括号等的匹配是 Perl 的新奇事物。

    这就是如何捕获 shell 脚本输出的基础知识。要打印 HTML 表格中的数字,您必须将捕获的输出拆分为单独的行(将它们保存到列表或数组中),然后打印您的 HTML 序言(<table><th>(标题)标签,等等on) ...它们遍历一系列 <tr> 行,将您的数字插入到 <td>>(表格数据)容器中),然后最后打印您的 HTML 结尾(带有结束标签)。

    为此,您需要阅读 Perl print 函数以及 Perl 中的“插值”。这是一个相当复杂的话题。

    这一切都非常粗糙,并且有一些工具可以让您在更高级别上处理 HTML 的生成。您是否希望将 shell 脚本的执行包装在 Perl 脚本中也是相当可疑的,因为您似乎可以修改 shell 脚本以直接输出 HTML(可能作为由命令行开关或环境变量控制的选项)或你可以用 Perl 重写 shell 脚本。这可能会消除解析输出的额外工作(将其拆分为行并将这些行中的值分离到一个数组中,因为您可以直接将数据捕获到数组中(或者可能打印出您的 HTML 行)。生成它们(但是您现有的 shell 脚本正在这样做)。

    【讨论】:

      【解决方案2】:

      要捕获 bash 文件的输出,您可以使用反引号运算符:

      use strict;
      my $e = `ls`;
      print $e;
      

      【讨论】:

      • 是的,但如果他没有 Perl 经验,至少包括 use strictmy $e = :)
      【解决方案3】:

      非常非常感谢您!在您的大力帮助下。我能够构建一个完成大部分工作的 perl 脚本。

      这是我迄今为止创建的:

      #!/usr/bin/perl -w
      use strict;
      use CGI qw(:standard);
      
      #some variables
      my $message = "please wait, loading data...\n";
      
      #First build the web page
      print header;
      print start_html('Hello World');
      print "<H1>we need love, peace and harmony</H1>\n";
      print "<p>$message</p>\n";
      
      #Establish a pipeline between the bash and my script.
      my $bash_command = '/love/peace/harmony/./lovepeace.bash';
      open(my $pipe, '-|', $bash_command) or die $!;
      
      while (my $line = <$pipe>){
      # Do something with each line.
      print "<p>$line</p>\n";
      }
      
      #job done, now refresh page?
      
      print end_html;
      

      当我在浏览器中调用该 .pl 脚本时,一切正常 :-) 但我仍然有几个问题:

      当我调用这个网站时,它正忙于从管道加载值。由于大约有 10 个值,所以它相当

      快速(2-4 秒)但如果我有 100 多个值,则用户必须等待一段时间。由于我不能有进度条,所以我

      应该给用户一个信息。喜欢:

      “正在加载数据,请稍候...”

      当工作完成时,这条消息应该说:“工作完成”或类似的东西。

      • 但是我如何知道流程是否已完成?
      • 如果作业完成,我可以重新加载页面吗?
      • 有没有机会在这个 perl-CGI 中使用我自己的样式表

      问候,

      JJ

      【讨论】:

      • 我建议您为此创建一个新问题。
      【解决方案4】:

      为什么只有 perl:

      您可以在 shell 脚本本身中使用 awk。 我之前已经这样做了。 如果变量中有输出值,请使用以下方法:

      echo $SUBSCRIBERS|awk 'BEGIN {
      print "<?xml version=\"1.0\" encoding=\"UTF-8\"?><GenTransactionHandler  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><EntityToPublish>\n<Entitytype=\"C\" typeDesc=\"Subscriber level\"><TargetApplCode>UHUNLD</TargetApplCode><TrxName>GET_SUBSCR_DATA</TrxName>" 
      }
      {for(i=1;i<NF+1;i++) printf("<value>%d</value>\n",$i)}
      END{
      print "</Entity>\n</EntityToPublish></GenTransactionHandler>"}' >XML_SUB_NUM`date +%Y%m%d%H%M%S`.xml
      

      $SUBSCRIBERS 中的值应该用制表符分隔。

      【讨论】:

        猜你喜欢
        • 2021-07-08
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        • 1970-01-01
        • 2019-01-25
        • 1970-01-01
        • 2017-11-21
        • 2015-03-08
        相关资源
        最近更新 更多