Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json Perl变量在循环中变得未定义_Json_Perl_Csv - Fatal编程技术网

Json Perl变量在循环中变得未定义

Json Perl变量在循环中变得未定义,json,perl,csv,Json,Perl,Csv,编辑:修改代码和输出,使其更清晰 编辑2:添加用于复制的示例输入 我有一个JSON文件和一个CSV文件,我正在对这两个文件进行比较。问题是$asset_ip在外部foreach循环中定义正确,但在嵌套循环中$asset_ip变得未定义 为什么$asset_ip变得未定义 #!/usr/bin/perl # perl -e'use CPAN; install "Text::CSV"' use strict; use warnings; use JSON::XS; use File::Slurp;

编辑:修改代码和输出,使其更清晰

编辑2:添加用于复制的示例输入

我有一个JSON文件和一个CSV文件,我正在对这两个文件进行比较。问题是$asset_ip在外部foreach循环中定义正确,但在嵌套循环中$asset_ip变得未定义

为什么$asset_ip变得未定义

#!/usr/bin/perl
# perl -e'use CPAN; install "Text::CSV"'
use strict;
use warnings;

use JSON::XS;
use File::Slurp;
use Text::CSV;
my $csv = Text::CSV->new( { sep_char => ',' } );

my $csv_source  = "servers.csv";
my $json_source = "assets.json";
my $dest = "servers_for_upload.csv";

# defined these here as I need to use them in foreach loop and if statement:
my $csv_ip;
my @fields;
open( my $csv_fh, '<', $csv_source ) or die "$! error trying to read";
open( my $dest_fh, '>', $dest ) or die "$! error trying to read";

my $json = read_file($json_source);
my $json_array = decode_json $json;

foreach my $item (@$json_array) {
    my $id = $item->{id};
    my $asset_ip = $item->{interfaces}->[0]->{ip_addresses}->[0]->{value};

    # test the data is there:
    if ( defined $asset_ip ) {
        print "id: " . $id . "\nip: " . $asset_ip . "\n";
    }

    while (my $line = <$csv_fh>) {
        chomp $line;
        if ( $csv->parse($line) ) {
            @fields = $csv->fields();
            $csv_ip = $fields[0];
        }
        else {
            warn "Line could not be parsed: $line\n";
        }

            if ( $csv_ip eq $asset_ip ) {
                # preppend id to csv array and write these lines to new file
                unshift( @fields, $id );
                print $dest_fh join( ", ", @fields );    
        }
    }
}
close $csv_fh;
注意,对于第一次迭代,$asset_ip将是未定义的。因此,如果定义了$asset_ip,我将修改代码以仅运行eq比较。然而,对于这个例子,我没有做检查,因为所有的迭代都是未定义的

servers.csv:

192.168.0.3,Brian,Germany
192.168.0.4,Billy,UK
192.168.0.5,Ben,UK

我认为你的问题是:

foreach my $line (<$csv_fh>) {
具体来说:

[{"id":1001,"interfaces":[]}
该数组中的第一个元素没有定义$asset\u ip

这意味着在您第一次通过时,$asset_ip未定义并生成错误。由于您的if定义测试,因此未打印任何行

但随后-代码继续遍历$csv_fh-读取到文件末尾-查找匹配项并失败3次,生成3条错误消息

第二次迭代-对于id 1002-IP无论如何都不在文件中,但是$csv_fh已经被读取到文件EOF的末尾-因此foreach循环根本不执行

这可以通过以下方式实现:

下一步添加其他内容;之后,如果定义。 在while循环之后添加seek。 但实际上,重写是正确的,这样你就不会一遍又一遍地阅读文件了

非常粗略地说:

#!/usr/bin/perl
# perl -e'use CPAN; install "Text::CSV"'
use strict;
use warnings;

use JSON::XS;
use File::Slurp;
use Text::CSV;
my $csv = Text::CSV->new( { sep_char => ',' } );

my $csv_source  = "servers.csv";
my $json_source = "assets.json";
my $dest        = "servers_for_upload.csv";

# defined these here as I need to use them in foreach loop and if statement:
my $csv_ip;
my @fields;
open( my $csv_fh,  '<', $csv_source ) or die "$! error trying to read";
open( my $dest_fh, '>', $dest )       or die "$! error trying to read";

my $json       = read_file($json_source);
my $json_array = decode_json $json;

foreach my $item (@$json_array) {
    my $id       = $item->{id};
    my $asset_ip = $item->{interfaces}->[0]->{ip_addresses}->[0]->{value};

    # test the data is there:
    if ( defined $asset_ip ) {
        print "id: " . $id . "\nip: " . $asset_ip . "\n";
    }
    else {
        print "asset_ip undefined for id $id\n";
        next;
    }

    while ( my $line = <$csv_fh> ) {
        chomp $line;
        if ( $csv->parse($line) ) {
            @fields = $csv->fields();
            $csv_ip = $fields[0];
        }
        else {
            warn "Line could not be parsed: $line\n";
        }

        if ( $csv_ip eq $asset_ip ) {

            # preppend id to csv array and write these lines to new file
            unshift( @fields, $id );
            print {$dest_fh} join( ", ", @fields ),"\n";
        }
    }
    seek( $csv_fh, 0, 0 );
}
close $csv_fh;
我认为这还需要:

更改while,这样您就不会每次都重新读取该文件 您正在使用Text::CSV,因此使用打印连接,。。。这似乎不是一个一致的选择。如果您的数据支持Text::CSV,那么也值得保留它以供输出。
与您的问题无关:应该在die'$中使用双引号,而不是单引号!尝试读取“”时出错。按原样,您将获得美元!如果发生这些错误,则替换为变量的值。抱歉-没有提及-我在运行脚本时遇到错误$asset_ip未定义。引用错误消息和行号有助于诊断。一些示例源数据也是如此。大概这就是您正在使用的JSON?你有一些CSV样本数据吗?我认为没有必要包含样本数据。简单地说,$asset_ip在外循环中定义为ip地址,但在内循环中则未定义。第二个循环对CSV文件中的行数进行正确的迭代次数。如果没有样本数据,我们无法重现问题,因此只能猜测是哪一行导致问题,以及如何导致问题。这就是为什么我们通常要求一个-没有明确的原因为什么它会变得未定义或在哪里它会变得未定义。但是在阅读/重读$csv_fh时有一个明显的逻辑错误。我只是在编辑摘要中写了一个诙谐的评论…:我会想象一些有趣而有见地的事情。一般来说,如果你不得不对一个文件的内容进行多次迭代,重新读取该文件可能不是一个好主意,因为操作系统无论如何都会缓存数据。当然,在这种情况下,存在更有效的单通道算法description@IlmariKaronen:操作系统可能会缓存内容,Perl自己的I/O层可能会进行一些缓冲,但如果文件中有足够的数据,您将看到重复的读取系统调用,从而导致不必要的内核上下文切换。。。抱歉吹毛求疵-
[{"id":1001,"interfaces":[]},{"id":1003,"interfaces":[{"ip_addresses":[{"value":"192.168.0.2"}]}]},{"id":1004,"interfaces":[{"ip_addresses":[{"value":"192.168.0.3"}]}]},{"id":1005,"interfaces":[{"ip_addresses":[{"value":"192.168.0.4"}]}]}]
[{"id":1001,"interfaces":[]}
#!/usr/bin/perl
# perl -e'use CPAN; install "Text::CSV"'
use strict;
use warnings;

use JSON::XS;
use File::Slurp;
use Text::CSV;
my $csv = Text::CSV->new( { sep_char => ',' } );

my $csv_source  = "servers.csv";
my $json_source = "assets.json";
my $dest        = "servers_for_upload.csv";

# defined these here as I need to use them in foreach loop and if statement:
my $csv_ip;
my @fields;
open( my $csv_fh,  '<', $csv_source ) or die "$! error trying to read";
open( my $dest_fh, '>', $dest )       or die "$! error trying to read";

my $json       = read_file($json_source);
my $json_array = decode_json $json;

foreach my $item (@$json_array) {
    my $id       = $item->{id};
    my $asset_ip = $item->{interfaces}->[0]->{ip_addresses}->[0]->{value};

    # test the data is there:
    if ( defined $asset_ip ) {
        print "id: " . $id . "\nip: " . $asset_ip . "\n";
    }
    else {
        print "asset_ip undefined for id $id\n";
        next;
    }

    while ( my $line = <$csv_fh> ) {
        chomp $line;
        if ( $csv->parse($line) ) {
            @fields = $csv->fields();
            $csv_ip = $fields[0];
        }
        else {
            warn "Line could not be parsed: $line\n";
        }

        if ( $csv_ip eq $asset_ip ) {

            # preppend id to csv array and write these lines to new file
            unshift( @fields, $id );
            print {$dest_fh} join( ", ", @fields ),"\n";
        }
    }
    seek( $csv_fh, 0, 0 );
}
close $csv_fh;