【问题标题】:how to define script interpreter with shebang如何用shebang定义脚本解释器
【发布时间】:2013-03-27 17:13:13
【问题描述】:

很明显可以使用

#!/usr/bin/perl

shebang 符号在脚本的第一行中定义解释器。但是,这以一个解释器为前提,它忽略了作为 cmets 的 hashmark 起始行。如何使用没有此功能的解释器?

【问题讨论】:

  • 你心目中的口译员是谁?我认为没有通用的解决方案,但也许有办法解决您的具体情况。
  • Poly/ML,最初不打算用作脚本语言,但我认为可以使用一些有目的的库。
  • 有趣的是,不使用# 作为注释字符的脚本语言有时会在这种情况下例外,仅在第一行。试试你的实现;它可能只是工作。
  • 一个简单的演示:将#!/bin/cat添加到文本文件的顶部,chmod +x文件,并执行它。它将打印文件的内容,包括 shebang。顺便说一句,poly 命令似乎不允许您将脚本名称指定为参数,尽管它可以从stdin 读取命令。即使忽略 # 问题,这也可能使其难以与 shebang 一起使用。

标签: linux bash unix sml


【解决方案1】:

使用包装器删除第一行并使用文件的其余部分调用真正的解释器。它可能看起来像这样:

#!/bin/sh

# set your "real" interpreter here, or use cat for debugging
REALINTERP="cat"

tail -n +2 $1 | $REALINTERP

除此之外:在某些情况下,可以选择忽略关于第一行的错误消息。

最后的手段:将解释器的注释字符代码支持到内核中。

【讨论】:

    【解决方案2】:

    我认为第一行是由操作系统解释的。 解释器将被启动并且脚本的名字作为它的第一个参数传递给脚本。 以下脚本“first.myint”调用解释器“myinterpreter”,它是来自下面 C 程序的可执行文件。

    #!/usr/local/bin/myinterpreter
    % 1 #########
    2 xxxxxxxxxxx
    333
    444
    % the last comment
    

    个人翻译示意图:

    #include <errno.h>
    #include <stdio.h> 
    #include <stdlib.h>
    #include <string.h>
    
    #define BUFFERSIZE  256                         /* input buffer size */
    
      int
    main ( int argc, char *argv[] )
    {
      char    comment_leader  = '%';                /* define the coment leader */
      char    *line = NULL;
      size_t  len   = 0;
      ssize_t read;
      //  char  buffer[BUFFERSIZE];
    
      // argv[0] : the name of this executable
      // argv[1] : the name the script calling this executable via shebang
    
      FILE  *input;                                 /* input-file pointer */
      char  *input_file_name = argv[1];             /* the script name    */
    
      input = fopen( input_file_name, "r" );
      if ( input == NULL ) {
        fprintf ( stderr, "couldn't open file '%s'; %s\n",
            input_file_name, strerror(errno) );
        exit (EXIT_FAILURE);
      }
    
      while ((read = getline(&line, &len, input)) != -1) {
        if ( line[0] != comment_leader ) {
          printf( "%s", line );                     /* print line as a test */
        }
        else {
          printf ( "Skipped a comment!\n" );
        }
      }
    
      free(line);
    
      if( fclose(input) == EOF ) {                  /* close input file   */
        fprintf ( stderr, "couldn't close file '%s'; %s\n",
            input_file_name, strerror(errno) );
        exit (EXIT_FAILURE);
      }
    
      return EXIT_SUCCESS;
    }   /* ----------  end of function main  ---------- */
    

    现在调用脚本(之前已成为可执行文件)并查看输出:

    ...~> ./first.myint
    #!/usr/local/bin/myinterpreter
    Skipped a comment!
    2 xxxxxxxxxxx
    333
    444
    Skipped a comment!
    

    【讨论】:

      【解决方案3】:

      我成功了。我特别感谢 holgero 的尾巴技巧

      tail -n +2 $1 | $REALINTERP
      

      那个,并且在 Stack Overflow 上找到这个答案使之成为可能:

      How to compile a linux shell script to be a standalone executable *binary* (i.e. not just e.g. chmod 755)?

      “完全满足我需求的解决方案是 SHC - 免费工具”

      SHC 是一个 shell 到 C 的翻译器,见这里:

      http://www.datsi.fi.upm.es/~frosal/

      所以我写了polyscript.sh

      $ cat polyscript.sh
      #!/bin/bash
      
      tail -n +2 $1 | poly
      

      我用 shc 编译,然后用 gcc 编译:

      $ shc-3.8.9/shc -f polyscript.sh
      $ gcc -Wall polyscript.sh.x.c -o polyscript
      

      现在,我能够创建第一个用 ML 编写的脚本:

      $ cat smlscript
      #!/home/gergoe/projects/shebang/polyscript $0
      
      print "Hello World!"
      

      而且,我能够运行它:

      $ chmod u+x smlscript
      $ ./smlscript
      Poly/ML 5.4.1 Release
      > > # Hello World!val it = (): unit
      

      Poly 没有抑制编译器输出的选项,但这不是问题。按照 fgm 的建议直接用 C 语言编写 polyscript 可能会很有趣,但这可能不会让它更快。

      所以,这就是这么简单。我欢迎任何 cmets。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-05
        相关资源
        最近更新 更多