【问题标题】:replace words with perl script reading from table (to anonymize names)用从表中读取的 perl 脚本替换单词(以匿名化名称)
【发布时间】:2016-08-21 23:33:36
【问题描述】:

我正在寻找一种用 perl 替换大文本中的单词的方法,并希望从另一个包含替换的文件中读取这些单词。我知道我能做到:

#!/usr/bin/perl

use warnings;
use strict;

open my $fh_in, '<', $ARGV[0] or die "No input: $!";
open my $fh_out, '>', $ARGV[1] or die "No output: $!";

while (<$fh_in>) 
{
    s/John/Jack/g;

    print $fh_out $_;
}   

... 并放置任意数量的 s/Fred/Frank/g; 行。 是否可以引用包含所有替换的外部文本文件?这是为了在采访中匿名化姓名。

我正在考虑以以下格式保存一个简单的文本文件:

Name    Pseudonym   
John    Jack  
Fred    Frank  
etc.

(以制表符分隔)
如果有更好的方法可以做到这一点,我会感谢您的建议。 原件来自一个 Excel 数据库,该数据库在两列中包含所有名称替换,但将其放入文本文件相当容易,而且我不想让它太复杂,因为我对脚本和东西不太熟悉。

【问题讨论】:

    标签: regex perl replace


    【解决方案1】:

    读取包含哈希对应的文件,然后像这样进行替换:

    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    open my $fh_in, '<', $ARGV[0] or die "No input: $!";
    open my $fh_out, '>', $ARGV[1] or die "No output: $!";
    
    open my $fh_pseudo, '<', "path/to/pseudo" or die "unable to open pseudo: $!";
    my %corres;
    while (<$fh_pseudo>) {
        chomp;
        my ($name, $pseudo) = split /\t/, $_;
        $corres{$name} = $pseudo if $name && $pseudo;
    }
    
    while (my $line = <$fh_in>) {
        $line =~ s/\b$_\b/$corres{$_}/g for keys %corres;
        print $fh_out $line;
    }   
    

    【讨论】:

    • 感谢您的快速回答。我收到一个错误,说:Use of uninitialized value $corres{""} in substitution iterator at /Users/me/Library/Scripts/script.pl line 18, &lt;$fh_in&gt; line 3.我正在使用perl script.pl input.txt output.txt从命令行运行@
    • 我也在第 12 行更正了 中似乎缺少一个“s”
    • @jan:我已经修改了脚本以考虑空名称或伪名称。另外,你说得对s.
    • 行得通!非常感谢。如果可以的话,再问一个问题:如果我想将该部分集成到另一个已经具有(相当复杂)while循环的脚本中,例如while (&lt;$fh_in&gt;) { if ...然后是其他一些东西...print $fh_out $_; }如何我把它们结合起来?我尝试一个接一个地写一个while 块,但没有成功。
    • @jan:最好的方法是在整个while循环中将$_更改为$line
    【解决方案2】:

    如果您阅读文件的所有内容,您将在内存中执行替换之前进行替换会更容易。

    您还应该注意不要替换特定的子字符串。如果您有输入文件:“Hello Fred”。在替换列表“Fred Frank”和“Frank Frankstein”中,您最终会得到“Hello Frankstein”...

    我将替换列表放在 DATA 部分下,以使其独立。

    use strict;                                                                      
    use warnings;                                                                    
    use utf8;                                                                        
    use IO::All;                                                                        
    
    my %list;                                                                        
    
    die "File not found or can't be read\n"                                          
    unless $ARGV[0] && -e $ARGV[0] && -r $ARGV[0];                                 
    
    die "Need an output file name\n" unless $ARGV[1];                                
    my $output = $ARGV[1];                                                           
    
    while (<DATA>) {                                                                 
        my ( $name, $nick ) = m/(\w+)\t(\w+)$/;                                      
        next unless $name && $nick;                                                  
        $list{$name} = $nick;                                                        
    }                                                                                   
    
    my $contents = io->file($ARGV[0])->slurp;                                           
    
    for my $name ( keys %list ) {                                                    
        $contents =~ s/\b$name\b/$list{$name}/g;                                         
    }                                                                                
    
    $contents > io($output);                                                         
    
    __DATA__                                                                         
    
    John    Jack                                                                     
    Fred    Frank
    

    【讨论】:

    • 谢谢。有两个原因,为什么我更喜欢将 DATA 放在单独的文件中。 (a) 这是一个更大设置的一部分,其中两个或三个已经进行其他替换的不同脚本应该作为最后一步进行匿名化,并且它们都需要相同的替换数据,并且 (b) 新名称将不断添加到文件,我宁愿不必将它们添加到所有脚本中。是否可以调整您的答案以将 DATA 部分与脚本本身分开?
    • 是的,很简单:open(my $fh, ") 更改为 while ()
    猜你喜欢
    • 1970-01-01
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 2020-03-12
    • 2018-08-18
    相关资源
    最近更新 更多