Экранирование круглых скобок в perl обратных кавычек для команды bash - PullRequest
2 голосов
/ 19 июня 2020

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

Я пробовал заключать в двойные кавычки и экранировать с помощью \ в нескольких местах, но, похоже, ничего не работает. Приветствуется любая помощь.

КОМАНДА $file5 и $file6 являются perl переменными, а не bash.

@array = `/usr/bin/join -j 1 -t, <(cat $file5 | awk -F, '{print \$3","\$1}' | sort) <( cat $file6 | awk -F, '{print \$3","\$1}' | sort) `

ОШИБКА: AH01215: sh: - c: строка 0: синтаксическая ошибка рядом с неожиданным токеном `(', referer:

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Обратные кавычки используют /bin/sh, и хотя <( ... ) является чем-то, что распознается bash, оно не распознается оболочкой bourne. Если вы используете обратные кавычки, вам нужно будет использовать команды оболочки

my $bash_cmd = ...;
my @lines = `bash -c $bash_cmd`;

Building sh и bash, используя String :: ShellQuote .

use String::ShellQuote qw( shell_quote );

my $file5_quoted = shell_quote($file5);
my $file6_quoted = shell_quote($file6);

my $awk_cmd = shell_quote("awk", "-F,", '{print $3","$1}');

my $bash_cmd = '/usr/bin/join -j 1 -t,'
   . " <( $awk_cmd $file5_quoted | sort )"
   . " <( $awk_cmd $file6_quoted | sort )";

my $sh_cmd = shell_quote("bash", "-c", $bash_cmd);
my @lines = `$sh_cmd`;

Мы можем использовать IP C :: System :: Simple s capturex, чтобы избежать запуска большего количества оболочек, чем необходимо, а также для обеспечения проверки ошибок. Для этого замените две последние строки вышеприведенного на следующее:

use IPC::System::Simple qw( capturex );

my @lines = capturex("bash", "-c", $bash_cmd);
0 голосов
/ 20 июня 2020

Одним из обходных путей является создание сценария оболочки, который принимает два имени файла из perl, обрабатывает соединение, используя эти два входных файла, и возвращает результат в массив perl.

#1. Create join.sh that contains these four lines:

    cat $1 | awk -F, '{print $3","$1}' | sort > 1.out
    cat $2 | awk -F, '{print $3","$1}' | sort > 2.out
    /usr/bin/join -j 1 -t, 1.out 2.out
    rm 1.out 2.out


#2. Modify your perl statement to call join.sh as follows:

    @array=`join.sh $file5 $file6`;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...