Как использовать обе трубы и предотвратить расширение оболочки в системной функции perl?

Если в системную функцию perl передано несколько аргументов, расширение оболочки не будет работать:

# COMMAND
$ perl -e 'my $s="*"; system("echo", "$s" )'

# RESULT
*

Если команда передается как один аргумент, расширение будет работать:

# COMMAND
$ perl -e 'my $s="echo *"; system("$s")'

# RESULT
Desktop Documents Downloads

Функция системы также позволяет использовать несколько команд и соединять их с помощью каналов. Это работает только когда аргумент передается как одна команда:

# COMMAND
$ perl -e 'my $s="echo * | cat -n"; system("$s")'

# RESULT
1 Desktop Documents Downloads

Как я могу объединить упомянутые команды и использовать обе трубы и предотвратить расширение оболочки?

Я пытался:

# COMMAND
$ perl -e 'my $s="echo"; system("$s", "* | cat -n")'

# RESULT
* | cat -n

но это не сработало по причинам, которые я описал выше (несколько аргументов не раскрываются). Результат, который я хочу получить:

1 *

РЕДАКТИРОВАТЬ: проблема, с которой я на самом деле сталкиваюсь, заключается в том, что, когда я использую следующую команду:

system("echo \"$email_message\" | mailx -s \"$email_subject\" $recipient");

Затем $email_message раскрывается, и он прерывает mailx, если он содержит некоторые символы, которые в дальнейшем расширяются оболочкой.

2 ответа

system имеет три соглашения о вызовах:

system($SHELL_CMD)

system($PROG, @ARGS)               # @ARGS>0

system( { $PROG } $NAME, @ARGS )   # @ARGS>=0

Первый передает команду в оболочку. Это эквивалентно

system('/bin/sh', '-c', $SHELL_CMD)

Два других выполняют программу $PROG, system никогда не предотвращает расширение оболочки и не выполняет какие-либо действия. Там просто нет оболочки.

Итак, ваш вопрос о сборке команды оболочки. Если бы вы были в приглашении, вы могли бы использовать

echo \* | cat -n

или же

echo '*' | cat -n

пройти *, Вам нужна функция, которая выполняет работу по спасению * перед интерполяцией К счастью, один уже существует: String:: ShellQuoteshell_quote,

$ perl -e'
   use String::ShellQuote qw( shell_quote );
   my $s = "*";
   my $cmd1 = shell_quote("printf", q{%s\n}, $s);
   my $cmd2 = "cat -n";
   my $cmd = "$cmd1 | $cmd2";
   print("Executing <<$cmd>>\n");
   system($cmd);
'
Executing <<printf '%s\n' '*' | cat -n>>
     1  *

я использовал printf вместо echo так как очень трудно обрабатывать аргументы, начинающиеся с - в echo, Большинство программ принимают -- отделить варианты от не-вариантов, но не мои echo,

Все эти осложнения задают вопрос: почему вы отправляете электронное письмо? Обычно обрабатывать ошибки из внешних программ гораздо сложнее, чем из библиотек.

Ты можешь использовать open направить напрямую в mailx, без интерпретации вашего содержимого оболочкой:

open( my $mail, "|-", "mailx", "-s", $email_subject, $recipient );
say $mail $email_message;
close $mail;

Более подробную информацию можно найти в открытом разделе Perlipc.

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