Как использовать синтаксис bash в системе Perl()?

Как я могу использовать синтаксис bash в команде Perl system()?

У меня есть команда bash -специфическая, например. следующее, использующее bash замену процесса:

 diff <(ls -l) <(ls -al)

Я хотел бы назвать это из Perl, используя

 system("diff <(ls -l) <(ls -al)")

но это дает мне ошибку, потому что вместо bash используется sh для выполнения команды:

sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `sort <(ls)'

Ответы

Ответ 1

Скажите Perl для прямого вызова bash. Используйте list вариант system(), чтобы уменьшить сложность вашего цитирования:

my @args = ( "bash", "-c", "diff <(ls -l) <(ls -al)" );
system(@args);

Вы даже можете определить подпрограмму, если вы планируете делать это достаточно часто:

sub system_bash {
  my @args = ( "bash", "-c", shift );
  system(@args);
}

system_bash('echo $SHELL');
system_bash('diff <(ls -l) <(ls -al)');

Ответ 2

 system("bash -c 'diff <(ls -l) <(ls -al)'")

должен сделать это теоретически. Bash -c позволяет вам передать команду оболочки для выполнения, в соответствии с man-страницей.

Ответ 3

Проблема с ответами vladr заключается в том, что система не будет выводить вывод в STDOUT из команды (которую вы обычно хотели бы), а также не позволяет выполнять более одной команды (учитывая использование сдвига, а не доступ к полному содержимому @_).

Что-то вроде следующего может быть больше подходит для проблемы:

my @cmd = ( 'diff <(ls -l) <(ls -al)', 'grep fu' );
my @stdout = exec_cmd( @cmd );
print join( "\n", @stdout );

sub exec_cmd
{
    my $cmd_str = join( ' | ', @_ );
    my @result = qx( bash -c '$cmd_str' );
    die "Failed to exec $cmd_str: $!" unless( $? == 0 && @result );
    return @result;
}

К сожалению, это не помешает вам вызвать /bin/sh только для запуска bash, однако я не вижу обходного пути для этой проблемы.

Ответ 4

Я предпочитаю выполнять команды bash в perl с обратными выводами "`". Таким образом, я получаю возвращаемое значение, например:

my $value = \`ls`;

Кроме того, мне не нужно использовать "bash -c", чтобы запустить commmand. Работает для меня.

Ответ 5

Вдохновленный ответом от @errant.info, я создал что-то более простое и работал у меня:

my $line="blastn -subject <(echo -e \"$seq1\") -query <(echo -e \"$seq2\") -outfmt 6";
my $result=qx(bash -c '$line');
print "$result\n";

Введенная переменная $line позволяет изменять входы ($ seq1 и $seq2) каждый раз. Надеюсь, это поможет!