perl - 用制表符/空格分隔输出

标签 perl

我正在处理三个文本文档。第一个是主输入(输入 1),其中单词和单词类型(名词、动词等)由制表符分隔。

输入1

John    N
goes    V
to      P
school  N
.       S
Mary    N
comes   V
from    P
home    N
.       S

第二个和第三个输入文本文件如下所示:

输入2

John
Mary

输入3

to
from

我的目标是将第二个和第三个文本文件与主输入进行比较和匹配,并获得如下输出:

预期输出:

John    N   N
goes    V
to      P   P
school  N
.       S
Mary    N   N
comes   V
from    P   P
home    N
.       S

所有三列均应以制表符或空格分隔。但是,我得到这样的输出:

John N  
N
goes    
V
to P    
P
school  
N
.   
S
Mary N  
N
comes   
V
from P  
P
home    
N
.   
S

我相信当我将第一个文本文件的输入放入数组并打印值时,就会发生这种情况。请建议一种获得所需输出的方法。

我使用的程序代码如下:

#!/usr/bin/perl

use warnings;
use strict;

my @file = ('Input 1.txt');

open my $word_fh, '<', 'Input 2.txt' or die $!;
open my $word2_fh, '<', 'Input 3.txt' or die $!;

my %words_to_match = map {chomp $_; $_ => 0} <$word_fh>;
my %words_to_match2 = map {chomp $_; $_ => 0} <$word2_fh>;

close $word_fh;
close $word2_fh;

check($_) for @file;

sub check {
    my $file = shift;

open my $fh, '<', $file or die $!;

while (<$fh>){
    chomp;
    my @words_in_line = split;

    for my $word (@words_in_line){
        $word =~ s/[(\.,;:!)]//g;
        $word .= '  N' if exists $words_to_match{$word};
        $word .= '  P' if exists $words_to_match2{$word};
        
        print "$word\n";
    }
    print "\n";
}

同样,目标是获得所有三列均由制表符或空格分隔的输出。

最佳答案

如果您首先读取所有引用文件并从中构建数据结构,然后读取主要输入文件并对其进行转换,事情就会变得容易得多

您使用两个哈希值,%words_to_match%words_to_match2 并存储每个元素的值为零。这是浪费信息,最好的办法是构建一个单个哈希,将每个引用文件中的单词与其词性相关联。 Input 2.txt 中的单词是名词,因此它们得到 N,而 Input 3.txt 中的单词是介词,因此它们得到一个P

然后您只需检查是否存在与Input 1.txt中的每个单词匹配的哈希元素,如果存在,则在打印记录之前附加其值

下面的程序创建一个如下所示的哈希 %pos,它将两个引用文件中的每个单词与其词性关联起来

( from => "P", John => "N", Mary => "N", to => "P" )

在最后的输入循环中,我使用了替换 s/// 将所有尾随空格(包括换行符)替换为三个空格和词性。制表符对于布局表格来说没有什么用处,首先是因为没有人能就制表符停止位置达成一致,其次是因为单个制表符并不总是将列对齐。根据前面数据中有多少个字符,您有时可能需要两个或更多

我希望它是清楚的

use strict;
use warnings 'all';
use autodie;

my %words;

my %files = (
    'input 2.txt' => 'N',   
    'input 3.txt' => 'P',   
);

while ( my ( $file, $pos ) = each %files ) {
    open my $fh, '<', $file;

    while ( <$fh> ) {
        s/\s+\z//;
        $words{$_} = $pos;
    }
}

{
    open my $fh, '<','input 1.txt';

    while ( <$fh> ) {
        next unless /\S/;
        my ($word) = split;
        my $pos = $words{$word};
        s/\s+\z/   $pos\n/ if $pos;
    }
    continue {
        print;
    }
}

输出

John    N   N
goes    V
to      P   P
school  N
.       S
Mary    N   N
comes   V
from    P   P
home    N
.       S

关于perl - 用制表符/空格分隔输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37974486/

相关文章:

perl - 如何传递一系列数字(例如 : 100 to 200) as command line argument in Perl?

Perl 通过正则表达式获取文件

perl - 如何从 Perl 中的 GFF3 文件获取范围内的所有功能?

python - Perl 或 Python : Convert date from dd/mm/yyyy to yyyy-mm-dd

perl - HTTP::请求在 header 中用连字符替换下划线

perl - 屏幕抓取 : Automating a vim script

regex - 用正则表达式替换字符时忽略 latex 宏

linux - 如何确定 Linux 机器上目录中最新创建的文件?

linux - Perl 升级会破坏 Linux 上的旧版本吗?

perl - 在perl中遍历哈希数组