Perl-эквивалент PHP escapeshellarg

Чтобы избежать строки, используемой в качестве аргумента оболочки, мы используем функцию escapeshellarg() в PHP. Имеет ли Perl эквивалентную функцию?

Ответы

Ответ 1

String::ShellQuote, но большую часть времени это не требуется. Вы просто можете избежать вызова оболочки путем тщательного программирования. Например, system принимает список аргументов вместо строки.

Лучшая практика:

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

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

Ответ 2

Perl может соответствовать следующей заявленной функции:

добавляет одинарные кавычки вокруг строки и кавычки/экранирует любые существующие одинарные кавычки

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

вот так:

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

Ответ 3

Это работает для меня в BASH:

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

Он основан на следующих утверждениях, взятых из справочной страницы BASH:

  • Входящие символы в одинарных кавычках сохраняют буквальное значение каждого символа в кавычках.
  • Одиночная кавычка может отсутствовать между одинарными кавычками, даже если ей предшествует обратная косая черта.
  • Закрывающие символы в двойных кавычках сохраняют буквальное значение всех символов в кавычках, за исключением $, `, \, и, когда расширение истории включено,!.

Из (2.) мы знаем, что обратная косая черта не может использоваться для выхода из одиночных qoutes, но из (3.) это подразумевает, что двойные кавычки сохраняют литеральное значение (aka escape) одинарных кавычек.

Также обратите внимание, что единственной целью кавычек является изменение значения цитируемых символов (не создаются специальные строковые объекты или подобные вещи), и после расширения все последовательные литералы объединяются вместе. Тогда 'foo''bar' совпадает с foobar.

То, что делает вышеприведенная функция, - это одинарная кавычка всей строки, так что никакой символ в ней не имеет особого значения. Однако, чтобы обеспечить присутствие символов одиночной кавычки, строка разбивается везде, где такие символы найдены, и выполняются следующие операции: предыдущая подстрока завершена ('), затем вводится двойная кавычка (см. "'"), и начинается следующая подстрока ('). Поэтому ' заменяется глобально на '"'"'.

Например (псевдокод):

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

Ответ 4

Я должен согласиться с @daxim. Но есть некоторые обстоятельства, при которых вы не можете использовать это, например, передавать команду через сокет в программу, которая не является perl или не имеет доступного модуля IPC. Я также посмотрел на регулярное выражение, данное @axeman, и это кажется мне немного сложным. Я мог ошибаться, но я думаю, что вам не нужно скрывать обратную косую черту в одиночных кавычках для команды. Итак, вы можете просто сделать это:

sub escapeshellarg {
    my $arg = shift;

    $arg =~ s/'/'\\''/g;
    return "'" . $arg . "'";
}

Если у кого-то есть причина, почему это может быть небезопасно, я хотел бы знать. Я протестировал его с помощью любого трюка, о котором я мог подумать, чтобы заставить оболочку выполнить произвольный код без успеха, что заставляет меня думать, что это регулярное выражение такое же, как и реализация PHP.

В реализации PHP он утверждает, что все, что он делает: добавляет одинарные кавычки вокруг строки и кавычки/экранирует любые существующие одинарные кавычки.

Это единственное, что делает это регулярное выражение. Мысли?