【问题标题】:Escape special characters in JSON string转义 JSON 字符串中的特殊字符
【发布时间】:2019-07-06 18:49:29
【问题描述】:

我有包含变量 $env->{'arguments'} 的 Perl 脚本,该变量应该包含一个 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`;

转义字符功能:

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

我想问你什么是正确的方法以及如何将该 JSON 字符串解析为有效的 JSON 字符串,我可以将其用作我的脚本的参数。

【问题讨论】:

  • 另见String::ShellQoute。另一种避免将参数交给 shell(因此需要转义)的替代方法是将其写入临时文件,然后将临时文件的文件名作为参数传递给脚本

标签: json perl escaping character


【解决方案1】:

您正在重塑 wheel

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"

【讨论】:

  • 我尝试将 docker 命令添加到该 shell_quote 并得到:cd /home/user/system/!project/_addons/Ext/PHPtest &amp;&amp; docker run --rm -v $(pwd):/app -w /app php php hello.php:未找到
  • 通过将 shell 命令传递给 shell_quote,您到底想完成什么?!?!它将产生'cd /home/user/system/!project/_addons/Ext/PHPtest &amp;&amp; docker run --rm -v $(pwd):/app -w /app php php hello.php',您显然尝试将其作为shell 命令执行,该命令将尝试执行名为cd /home/user/system/!project/_addons/Ext/PHPtest &amp;&amp; docker run --rm -v $(pwd):/app -w /app php php hello.php 的文件。该文件“未找到”是轻描淡写!
  • @ikegame 但你不理解我,如果我只通过 backsticks 运行它,该命令是有效的并且文件存在,但我只是改变了它,我只将文件和参数包装到 shell_quote 和它有效。
  • 不,我所说的毫无疑问是正确的。没有名为cd&lt;space&gt; 的目录,更不用说路径cd /home... 中的文件了。您收到错误是因为您执行了 shell 命令 'cd /home...' 而不是 shell 命令 cd /home...。也就是说,即使我可以告诉你你做了什么,以及你告诉我的那一点点为什么错了,我不知道你为什么这样做,或者你想要实现什么。但这里不是那个地方。如果您有新问题,请发布新问题。
【解决方案2】:

将它传递给您的第二个程序而不是将其作为参数传递似乎更有意义(并且更安全)。

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)~);

【讨论】:

  • 非常感谢,但我真的很想使用参数,因为这样我就可以使用 docker 命令调用该脚本。
猜你喜欢
  • 2013-09-08
  • 2011-05-11
  • 2011-05-07
  • 1970-01-01
  • 2017-12-01
  • 2016-01-05
  • 1970-01-01
  • 2013-10-11
  • 2021-01-09
相关资源
最近更新 更多