将php函数转换为bash字符串

时间:2016-10-08 11:07:58

标签: php linux bash shell

我正在尝试编写一个bash脚本,在这样的php函数中添加一行:

public function register()
{
    $this->app->bind('App\Repositories\Corporate\CorporateContract',
        'App\Repositories\Corporate\EloquentCorporateRepository');
}

这是我的代码:

function bindContractToRepository {
   sed -i -e '/register()\n/a \ \n\t\t'${repoBinding}' \n\t\t\t\t ' ./app/Providers/${repoName}${provider}.php 2> /dev/null
}
bindContractToRepository

我实际上希望我的代码能够进入函数本身,就像顶部的示例一样。

NB。我无法指定特定行,因为行号因版本不同而不同

1 个答案:

答案 0 :(得分:0)

通常没有解析器就很难检测PHP函数边界。

我们可以在Bash中完成解析器的工作:逐行迭代代码,解决打开和关闭括号等问题,直到我们得到此函数覆盖的行数范围,最后用新的替换它内容。我们可以使用sed commands执行相同的操作(在这种情况下,可能看起来不像汇编代码那么可读)。

但是我们已经有了一个PHP解析器!为什么不使用它?

实施例

以下PHP CLI脚本接受:

  • PHP输入文件(我们将替换方法/函数);
  • PHP方法/功能名称
  • 替换为字符串的PHP代码字符串,或破折号(标准输入)

<强>更换-method.php

<?php
function usage($error = false) {
  global $argv;

  $str = <<<EOS
USAGE: php {$argv[0]} OPTIONS

OPTIONS:

-h, --help         Print help message
-i, --input-file   Input PHP file
-m, --method       PHP function/method name, e.g.:
                   my_func, MyClass::myMethod
-c, --code         The new PHP code including the function/method declaration.
                   String of code, or dash ('-') meaning the standard input.

EXAMPLE:

php {$argv[0]} -i source/file.php -m 'MyClass::register' -c - <<ENDOFPHP
  public function register()
  {
    echo time();
  }

ENDOFPHP

Replaces the code of 'MyClass::register' method with new code from the standard input
in source/file.php.

EOS;
  fprintf($error ? STDERR : STDOUT, $str);
  exit((int)!$error);
}

if (false === ($opt = getopt('hi:m:c:', ['help', 'input-file:', 'method:', 'code:']))) {
  fprintf(STDERR, "Failed to parse options\n");
  usage(true);
}


if (isset($opt['h']) || isset($opt['help']))
  usage();

// Using PHP7 Null coalescing operator
$file = $opt['i'] ?? $opt['input-file'] ?? null;
if (!file_exists($file)) {
  fprintf(STDERR, "File '$file' does not exist\n");
  usage(true);
}

$new_code = $opt['c'] ?? $opt['code'] ?? null;
if (!$new_code) {
  fprintf(STDERR, "Code option expected\n");
  usage(true);
}
if ($new_code == '-')
  $new_code = file_get_contents('php://stdin');

$method = $opt['m'] ?? $opt['method'] ?? null;
if (!$method) {
  fprintf(STDERR, "Method option expected\n");
  usage(true);
}

// You most likely want to include project's autoloading file instead.
// (You might accept it as a CLI argument, too.)
require_once $file;

$rf = strpos($method, '::') ?
  new ReflectionMethod($method) :
  new ReflectionFunction($method);
$start_line = $rf->getStartLine();
$end_line = $rf->getEndLine();

$lines = file($file);

$code = implode(array_slice($lines, 0, $start_line - 1)) .
  $new_code . implode(array_slice($lines, $end_line));

file_put_contents($file, $code);

假设我们path/to/file.phpA类及其register方法:

<?php
class A
{
  public function register()
  {
    echo 'aaaa';
  }
}

我们可以在Bash中替换A::register方法的代码,如下所示:

php replace-method.php -i path/to/file.php -m 'A::register' -c - <<ENDOFPHP
  public function register()
  {
    echo 'something new';
  }
ENDOFPHP

我已在此处使用Bash文档进行输入。您可以使用任何类型的shell重定向,例如:

generate_php_code | php 1.php -i file.php -m 'A::register' -c -