Perl建议 - 读入文件并更改内容

3

我有一个请求,需要一些关于如何编写Perl脚本的建议。基本上,我有一个看起来像这样的文件:

  id: 1
  Relationship: ""
  name: shelby
  pet: 1
  color:4

有一些关键字,如pet和color,后面跟着数字。我想要能够读入文件并查找这些关键字(大约有5或6个),然后将数字更改为对应的单词。也就是说,对于关键字“Pet”---> 0 =狗,1 =猫,2=鱼。而对于关键字“color”,0 =红色,1=蓝色,2=紫色,3=棕色,4=白色。脚本应该查找并更改这些数字。目标是一个输出文件,看起来像:

      id: 1
      Relationship: ""
      name: shelby
      pet: cat
      color:white

我已经苦苦思索了一段时间如何解决这个问题。我在网上查找了一些信息,可能可以使用哈希数组之类的东西,但我对Perl相对较新,甚至不知道如何解决这个问题...... 如果有任何建议,将不胜感激!

谢谢

5个回答

2

如果我们谈论的是一小组值,您可以使用数组哈希表:

%lookups = ( pet => [ "dog", "cat", "fish" ],
             color => [ "red", "blue", "purple", "brown", "white" ] );

接着,当你读取文件时,检查每个关键词是否与哈希表中的关键词匹配。如果它有一个与该关键词相对应的键,则将读取行中的值替换为哈希表中的值。


嗯,我没有考虑过对数组进行哈希。我会研究一下,谢谢。 - user899604

0

这应该可以了

use strict;

my $inputFileName = 'E:\test.txt';
my $outputFileName = 'E:\test2.txt';


my %Colors = ( 1 => 'Red' , 2 => 'Green' , 4 => 'Blue' );
my %Pets = ( 1 => 'Dog' , 2 => 'Cat' );

open( IN , "<" , $inputFileName) or die "$inputFileName could not be opened $!";
open( OUT, ">" , $outputFileName) or die "$outputFileName could not be opened $!";

while(<IN>)
{
    my $line = $_;
    if (/^(\s*pet\s*:\s*)(\d+)/ )
    {
        $line = $1. $Pets{$2} . "\n";
    }
    elsif (/\s*^color\s*:\s*(\d+)/ )
    {
       $line = $1. $Colors{$2} . "\n";
    }

    print OUT $line;
}
close(IN);
close(OUT);

如果我想从命令行读取文件,我只需要更改“my $inputFileName = $ARGV [1]”对吗? - user899604
$ARGV[1] 是第二个参数,而 $ARGV[0] 是第一个。但为什么要把事情弄复杂呢?如果你是在使用命令行文件名,只需使用 while (<>),它将自动为您打开文件。 - TLP

0
如果情况不是很多,你可以尝试像这样的东西,使用perl -p运行:
if (/^id/) 
{
    s/\d+/%h=(1=>"dog",2=>"warf",3=>"ee");$h{$&}/e;
}
if (/^other/) 
{ 
    s/\d+/%h=(1=>"other_thing",3=>"etc",4=>"etc2");$h{$&}/e;
}

编辑:

为了自动化测试,您可以像这样做(也可以从zigdon的哈希思路中借鉴):

my @interesting_tags = ("color", "pet");
my $regexp = "(" .  join("|" , @interesting_tags) . ")";

my %lookups = ( pet => [ "dog", "cat", "fish" ],
                color => [ "red", "blue", "purple", "brown", "white" ] );


while (<>)
{
    if (/$regexp/)
    {
        my $element = $&;
        s/\d+/$lookups{$element}[$&]/e;
    }
}

不幸的是,我将需要查找大约20个事项,但每个事项只与大约4个数字相关联。但如果我找不到更优雅的解决方案,使用一堆IF语句也可以解决问题。 - user899604

0

使用zigdon的建议

#!/usr/bin/perl
use strict;
use warnings;
use 5.014;

my %param = (pet   => [qw/dog cat fish/],
             color => [qw/ red blue purple brown white/],
);

while (<DATA>) {
    if (/^(pet|color):\s*(\d)$/) {
        print "$1: $param{ $1 }[$2]\n";
    }
    else {
        print;  
    }
}


__DATA__
id: 1
Relationship: ""
name: shelby
pet: 1
color:4

0
用法: script.pl file.txt > output.txt
use strict;
use warnings;

my %tags = (
    "pet" => [ qw(dog cat fish) ],
    "color" => [ qw(red blue purple brown white) ],
);

my $rx = join '|', keys %tags;

while (<>) {
    s/^\s*($rx):\s*(\d+)/$1: $tags{$1}[$2]/;
    print;
}

我有一个后续问题。如果我想要像将所有的分号改为等号这样的操作,我是必须要两次遍历文件还是可以在 while(<>) 中完成呢? - user899604
s/;/=/g。您可能需要在文档中阅读有关这些内容的信息:链接 - TLP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接