Избегайте специальных символов в строке JSON - PullRequest
0 голосов
/ 06 июля 2019

У меня есть скрипт Perl, который содержит переменную $env->{'arguments'}, эта переменная должна содержать объект JSON, и я хочу передать этот объект JSON в качестве аргумента моему другому внешнему сценарию и запустить его с помощью обратных галочек.

Значение$env->{'arguments'} перед экранированием:

$VAR1 = '{"text":"This is from module and backslash \\ should work too"}';

Значение $env->{'arguments'} после экранирования:

$VAR1 = '"{\\"text\\":\\"This is from module and backslash \\ should work too\\"}"';

Код:

print Dumper($env->{'arguments'});
escapeCharacters(\$env->{'arguments'});
print Dumper($env->{'arguments'});

my $command = './script.pl '.$env->{'arguments'}.'';
my $output = `$command`;

Функция Escape-символов:

sub escapeCharacters
{
    #$env->{'arguments'} =~ s/\\/\\\\"/g;
    $env->{'arguments'} =~ s/"/\\"/g;
    $env->{'arguments'} = '"'.$env->{'arguments'}.'"';
}

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

Ответы [ 2 ]

2 голосов
/ 06 июля 2019

Вы заново изобретаете колесо .

use String::ShellQuote qw( shell_quote );

my $cmd = shell_quote('./script.pl', $env->{arguments});
my $output = `$cmd`;

В качестве альтернативы, есть ряд IPC :: модулей, которые вы можете использовать вместо qx.Например,

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

my $output = capturex('./script.pl', $env->{arguments});

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

my $output = '';
open(my $pipe, '-|', './script.pl', $env->{arguments});
while (<$pipe>) {
   $output .= $_;
}

close($pipe);

Обратите внимание, что текущий каталог не обязательно является каталогом, которыйсодержит скрипт, который выполняетсяЕсли вы хотите выполнить script.pl, который находится в том же каталоге, что и текущий выполняемый скрипт, вам нужно внести следующие изменения:

Добавить

use FindBin qw( $RealBin );

и заменить

'./script.pl'

с

"$RealBin/script.pl"
1 голос
/ 06 июля 2019

Передача в вашу вторую программу вместо передачи ее в качестве аргумента кажется более разумной (и намного более безопасной).

test1.pl

#!/usr/bin/perl

use strict;
use JSON;
use Data::Dumper;

undef $/;

my $data = decode_json(<>);
print Dumper($data);

test2.pl

#!/usr/bin/perl

use strict;
use IPC::Open2;
use JSON;

my %data = ('text' => "this has a \\backslash", 'nums' => [0,1,2]);
my $json = JSON->new->encode(\%data);

my ($chld_out, $chld_in);
print("Executing script\n");
my $pid = open2($chld_out, $chld_in, "./test1.pl");
print $chld_in "$json\n";
close($chld_in);
my $out = do {local $/; <$chld_out>};
waitpid $pid, 0;
print(qq~test1.pl output =($out)~);
...