【问题标题】:Perl equivalent of PHP's escapeshellargPerl 等效于 PHP 的 escapeshellarg
【发布时间】:2011-03-13 19:57:41
【问题描述】:

为了转义用作 shell 参数的字符串,我们在 PHP 中使用函数 escapeshellarg()Perl 有等效功能吗?

【问题讨论】:

    标签: php perl


    【解决方案1】:

    String::ShellQuote,但大多数时候不需要。您只需仔细编程即可避免调用 shell。例如,system takes a list of arguments 而不是字符串。

    最佳实践:

    use IPC::System::Simple qw(systemx);
    systemx($command, @arguments);
    

    require IPC::System::Simple;
    use autodie qw(:all);
    system([@allowed_exit_values], $command, @arguments);
    

    【讨论】:

    • 是的,如果可能的话,完全避免使用 shell。
    • 用正确的解决方案回答XY question 做得很好。 :)
    • 当您需要重定向(因此不能使用 system() 调用的列表形式)来自变量的参数时,这可以提供帮助吗?例如对ls 'f o o' 的以下失败尝试的解决方案:my $foo='f o o'; my $result = `ls $foo 2>&1`; ?
    • 是 --- 尽可能避免 shell 解析。但这并不总是可能的。
    • 另外,use IPC::System::Simple qw(systemx EXIT_ANY $EXITVAL); systemx(EXIT_ANY, $command, @arguments); 将防止异常并在$EXITVAL 中指示成功。见IPC::System::Simple#ADVANCED_SYNOPSIS
    【解决方案2】:

    Perl 可以匹配下面的声明函数:

    在字符串周围添加单引号并引用/转义任何现有的单引号

    http://php.net/manual/en/function.escapeshellarg.php#function.escapeshellarg

    像这样:

    sub php_escapeshellarg { 
        my $str = @_ ? shift : $_;
        $str =~ s/((?:^|[^\\])(?:\\\\)*)'/$1'\\''/g;
        return "'$str'";
    }
    

    【讨论】:

    • 这不起作用。考虑将字符串 foo'bar 传递给函数。它将产生以下字符串:'foo\'bar'。但是单引号内不能有转义的单引号。
    【解决方案3】:

    我必须同意@daxim。但是在某些情况下您不能使用它,例如通过套接字将命令传递给不是 perl 或没有可用 IPC 模块的程序。我还查看了@axeman 给出的正则表达式,这对我来说似乎有点复杂。我可能是错的,但我认为您不需要为命令转义单引号字符串中的反斜杠。所以,你可以这样做:

    sub escapeshellarg {
        my $arg = shift;
    
        $arg =~ s/'/'\\''/g;
        return "'" . $arg . "'";
    }
    

    如果有人有任何理由,为什么这可能不安全,我想知道。我已经使用我能想到的任何技巧对其进行了测试,以使 shell 执行任意代码,但没有成功,这让我认为这个正则表达式与 PHP 实现相同。

    在 PHP 实现中,它声明它所做的只是:在字符串周围添加单引号并引用/转义任何现有的单引号。

    这是这个正则表达式唯一做的事情。 想法?

    【讨论】:

    【解决方案4】:

    这个在 BASH 中对我有用:

    sub escape_shell_param($) {
       my ($par) = @_;
       $par =~ s/'/'"'"'/g;  # "escape" all single quotes
       return "'$par'";      # single-quote entire string
     }
    

    它基于 BASH 手册页中的以下语句:

    1. 用单引号括起来的字符会保留引号内每个字符的字面值。
    2. 单引号之间不能出现单引号,即使前面有反斜杠。
    3. 将字符括在双引号中会保留引号内所有字符的字面值,但 $、`、 \,并且,当启用历史扩展时,!。

    从 (2.) 我们知道反斜杠不能用于转义单引号,但从 (3.) 可以看出,双引号会保留(也称为转义)单引号的字面值。

    还要注意引号的唯一目的是改变引号字符的含义(不创建特殊的字符串对象或类似的东西),并且在扩展后所有连续的文字字符都连接在一起。那么'foo''bar'就等于foobar

    上面的函数所做的是对整个字符串进行单引号,这样其中的字符就没有特殊含义了。但是,为了允许单引号字符的存在,字符串会在找到此类字符的任何位置进行拆分,并完成以下操作:前一个子字符串完成('),然后引入双引号单引号( "'") 并开始下一个子字符串 (')。这就是为什么' 被全局替换为'"'"'

    例如(伪代码):

    foo'bar => 'foo' + "'" + 'bar'
    

    【讨论】:

      猜你喜欢
      • 2014-09-29
      • 2012-02-24
      • 2011-11-13
      • 1970-01-01
      • 1970-01-01
      • 2017-07-15
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多