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?
Спасибо!
Я пробовал основные перестановки, такие как:
-
my @cmd = ('ls', "--color='auto'");
-
my @cmd = ('ls', '--color=\'auto\'');
-
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"
, он передает программе два аргумента:
-
ls
-
--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(), но мне было проще просто удалить кавычки.