Как использовать обе трубы и предотвратить расширение оболочки в системной функции 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.