【问题标题】:Reading File and Inserting into Variables using Perl使用 Perl 读取文件并插入变量
【发布时间】:2017-02-03 14:04:35
【问题描述】:

我是 Perl 的新手,所以请坦白我的无知。我想要做的是读取一个文件(已经使用 File::Slurp 模块)并从文件中的数据创建变量。目前我有这个设置:

use File::Slurp;
my @targets = read_file("targetfile.txt");
print @targets;

在该目标文件中,我有以下数据:

身份证号:123456789

名称:anytownusa

1.2.3.4/32

5.6.7.8/32

第一行是 ID,第二行是名称,所有后续行都是 IP 地址(最大长度为几百)。

所以我的目标是读取该文件并创建如下所示的变量:

$var1="123456789";

$var2="anytownusa";

$var3="1.2.3.4/32,5.6.7.8/32,etc,etc,etc,etc,etc";

** 请注意,所有 IP 地址最终都会组合到一个变量中,并用 (,) 逗号分隔。

【问题讨论】:

    标签: perl


    【解决方案1】:

    File::Slurp 将一次性读取完整的文件数据。如果文件很大,这可能会导致问题。让我向您展示解决此问题的简单方法。

    1. 使用while循环逐行读取文件
    2. 使用$.检查行号并将行数据分配给相应的变量
    3. 将 ips 存储在数组中,最后使用 join 打印它们

    注意:如果您必须更改行数据,请在将行数据分配给变量之前在相应的条件块中使用搜索和替换。

    代码:

    #!/usr/bin/perl
    use strict;
    use warnings;
    my ($id, $name, @ips);
    
    while(<DATA>){
        chomp;
        if ($. == 1){
            $id = $_;   
        }
        elsif ($. == 2){
            $name = $_;
        }
        else{
            push @ips, $_;  
        }
    }
    
    print "$id\n";
    print "$name\n";
    print join ",", @ips;
    
    __DATA__
    id: 123456789
    name: anytownusa
    1.2.3.4/32
    5.6.7.8/32
    

    Demo

    【讨论】:

    • 如何让 $id 和 $name 只输出 123456789 和 anytownusa?排除 id: 和 name: 字段?
    • 正如我所说,使用搜索和替换来更改数据。 $id =~ s/id: //g$name =~ s/name: //g 可以。
    【解决方案2】:

    正如已经指出的那样,没有理由将整个文件“slurp”变成一个变量。如果没有别的,它只会使处理更难。 另外,为什么不将命名标签存储在哈希中,在这个例子中

    my %identity = (id => 123456789, name => 'anytownusa');
    

    下面的代码从文件中提取键名,它们不是硬编码的。

    然后

    use warnings;
    use strict;
    use feature 'say';
    
    my (@ips, %identity);
    
    my $file = 'targetfile.txt';
    open my $fh, '<', $file or die "Can't open $file: $!";
    
    while (<$fh>) 
    {
        next if not /\S/;
        chomp;
    
        my ($m1, $m2) = split /:/;                #/(stop bad syntax highlight)
    
        if ($m1 and $m2) { $identity{$m1} = $m2; }
        else             { push @ips, $m1;       }
    }
    
    say "$_: $identity{$_}" for keys %identity;
    
    say join '/', @ips;
    

    如果该行没有:split 将返回整个行,这将是 ip,并存储在一个数组中以供以后处理。否则,它返回命名的对,用于'id''name'

    我们首先跳过了next if not /\S/; 的空白行,因此该行必须有一些非空格元素并且else 就足够了,因为$m1 中总是有一些东西。我们还需要删除换行符,chomp

    【讨论】:

    • 目标文件发生变化,因此 id、name 和 IP 始终是新的。你会如何调整这段代码?
    • @Alby 你的意思是值/名称会改变吗?这就是这种方法的要点。它使用: 读取anything 并选择它的“名称”和“值”——无论“名称”是什么。对于一行上的单个条目(当行上没有: 时),它只是将其放入一个数组中。这些是否混合,在哪些行上,或者它们被称为什么都没有关系。
    • 谢谢.. 是的,只是值发生了变化。单词“id:”和“name:”保持不变,但值会随着 IP 的变化而变化。
    • @Alby 好的。每次运行时都会重新读取文件,并在读取文件时获取其中的内容。至于idname——它每次都会得到它们,这很好。 (并且不依赖于行号,不受空行等的困扰)。此外,如果他们要更改或添加新的此类项目,它仍然可以工作。
    • @Alby 哦……抱歉,这是一个错字——应该是$identity{$m1},而不是%。它是一个哈希值,是一个标量,因此需要一个$。帖子里改了。另一个是因为第一个。
    【解决方案3】:

    直接将文件读入变量:

    use Modern::Perl;
    
    my ($id, $name, @ips) = (<DATA>,<DATA>,<DATA>);
    chomp ($id, $name, @ips);
    say $id;
    say $name;
    $" = ',';
    say "@ips";
    
    __DATA__
    id: 123456789
    name: anytownusa
    1.2.3.4/32
    5.6.7.8/32
    

    输出:

    id: 123456789
    name: anytownusa
    1.2.3.4/32,5.6.7.8/32
    

    【讨论】:

    • 我的 ($id, $name, @ips) = (,,);读入文件?假设该文件名为 target.txt。
    • @Alby:&lt;DATA&gt;用于读取_DATA_之后的数据。要读取您的真实文件,您必须先打开它,将 &lt;DATA&gt; 替换为文件句柄 &lt;$FILEHANDLE&gt;
    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 2012-11-02
    • 2019-08-17
    • 2022-12-31
    • 1970-01-01
    • 2019-02-01
    • 2011-05-04
    • 2011-06-27
    相关资源
    最近更新 更多