perl IPC::Open3 добавляет дополнительные кавычки к аргументам команды, имеющим кавычки.

Я пытаюсь использоватьIPC::Open::open3()(ну, правда, но это вызывает)... и у него странное поведение: если я передаю параметр командной строки с кавычками,open3()добавит дополнительные кавычки вокруг этой опции (иногда экранированные).

Например: я пытаюсь запуститьls --color="auto"и мой результат:

ls: unsupported --color value '"auto"' (must be always, auto, or never)

Вот код:

      package test;
use strict;
use warnings FATAL => 'all';

use IPC::Open3;
use POSIX;
use Symbol qw/ gensym /;

my @cmd = ('ls', '--color="auto"');

my $child_stdout;
my $child_stderr = gensym;

my $child_pid = IPC::Open3::open3(undef, $child_stdout, $child_stderr, @cmd);
my @out = <$child_stdout>;
my @err = <$child_stderr>;
close($child_stdout);
close($child_stderr);
waitpid($child_pid, POSIX::WNOHANG);

print join("", @out);
print join("", @err);
1;

ПРИМЕЧАНИЕ. Я понимаю, что могу бежатьls --color=auto... но я запускаю еще одну команду, которая принимает строки с пробелами, которые требуют кавычек, ls - это просто воспроизводимый пример.

Я пытался выяснить, где в источнике IPC::Open3 добавляет кавычки, но мне не удалось понять, где это происходит.

Короче говоря:

  • Кто-нибудь знает, как остановить поведение IPC::Open3, добавляющее кавычки в аргументы команды?
  • Есть ли другой модуль или метод IPC, который я мог бы использовать вместо вызова IPC::Open3?

Спасибо!

Я пробовал основные перестановки, такие как:

  1. my @cmd = ('ls', "--color='auto'");
  2. my @cmd = ('ls', '--color=\'auto\'');
  3. my @cmd = ('ls', "--color=\"auto\"");

Я пробовал использоватьIPC::Run::run()вот так:$success = IPC::Run::run(@cmd, \$in, \$out, \$err, IPC::Run::timeout(5));

Однако я не могу найти способ предотвратитьIPC::Open3из двойного кавычки.

2 ответа

В sh-ish оболочках все следующие действия приводят к получению токена:

  • '--color=auto'
  • "--color=auto"
  • --color="auto"
  • \-\-c'o'l"o"r\=auto

Итак, когда вы используете команду оболочкиls --color="auto", он передает программе два аргумента:

  1. ls
  2. --color=auto

Итак, вы хотите

      my @cmd = ( 'ls', '--color=auto' );

Предупреждение

Следующие действия могут привести к тупику:

      my @out = <$child_stdout>;
my @err = <$child_stderr>;

Чтобы сделать это безопасно, вам придется использовать сложный цикл выбора или аналогичный.

Или вы можете использовать другой модуль.

      use IPC::Run qw( run );

my @cmd = ( 'ls', '--color=auto' );

run \@cmd,
   '<',  '/dev/null',
   '>',  \my $out,
   '2>', \my $err;

die( "Child killed by signal ".( $? & 0x7F )."\n" ) if $? & 0x7F;
die( "Child exited with error ".( $? >> 8 )."\n"  ) if $? >> 8;

Оказывается, это не имеет ничего общего с IPC::Open3, но это особенность поведения Perl, когда он экранирует кавычки частей строк, чтобы иметь возможность распечатать их позже. В итоге я использовал Data::Dumper::Dumper() сразу после установки @cmd, и он уже был в кавычках. Итак, мне пришлось удалить все кавычки и использовать «—param=twoword» при передаче параметра. Я не думал, что это сработает, но поскольку в конечном итоге это собственный параметр, передаваемый в execve/posix_spawn/whatever, нет необходимости заключать значение параметра в кавычки с пробелами.

Извините, что сбил людей с пути примером «—-color='auto».

Другая возможность заключалась в том, чтобы попробовать String::Escape::unprintable(), но мне было проще просто удалить кавычки.

Другие вопросы по тегам