如何搜索从两个列表中取出的一对单词

时间:2017-05-10 13:38:19

标签: regex perl

我需要编写一个Perl脚本,在XML标签的句子开头用法语文本查找时间和位置实体。例如<temps> En été </temps>(“夏天”)。

我在CSV文件中列出了位置名称,并在文本文件中列出了时刻列表(冬季,夏季,周一,周二等)。我读了两个数组@topo@tabplace中的列表,原始文件每行一个单元格。

我想通过搜索以 En à le 等开头的句子来检测实体(in,at等)结果存储在@entites中。然后我需要分隔时间实体并放置实体:地点实体将存储在@places中,时间实体将存储在@times中。

我的问题是如何找到@entites的任何条目,然后是@topo的任何条目以及@times

中存储的所有结果

我在想这样的事情,但我错过了一些步骤:

foreach my $celtime ( @entite ) {
    @times = ( grep(/\b@entites.@tabtime/)
}

您的信息是完整的项目代码:

my @phrases  = ();
my @topo     = ();
my @entite   = ();
my @tabplace = ();
my @tabtime  = ();
my $fichiertexte;
my $celplace;
my $fichiertemps = 'entitemps.txt';
my $fichiertopo  = 'toponymes.csv';
my $lignedic;
my $lignetemps;

print "Quel fichier voulez-vous segmentez ?\n";
$fichierstexte = <STDIN>;
chomp( $fichiertexte );

open( TEXT, ">>:encoding(utf8)", $fichiertexte )
        or die( "Impossible d'ouvrir le fichier : ", $!, "\n" );
my @phrases = split( /\./, $lignetexte );  # Chaque phrase sur une ligne
while ( $lignetexte = <FICH> ) {
    chomp( $lignetexte );
    push( @phrases, $lignetexte );
}
close( TEXT );

open( TEMPS, ">>:encoding(utf8)", $fichiertemps )
        or die( "Impossible d'ouvrir le fichier : ", $!, "\n" );
while ( $lignetemps = <FICH> ) {
    chomp( $lignetemps );
    push( @tabtime, $lignetemps );  # @tabtime = tableau des noms de temps
}
close( TEMPS );

open( DICO, "<:encoding(utf8)", $fichiertopo )
        or die( "Impossible d'ouvrir le fichier : ", $!, "\n" );
while ( $lignedic = <FICH> ) {
    chomp( $lignedic );
    push( @topo, $lignedic );  # @topo = tableau des noms de lieu
}
close( DICO );

foreach my $cellule ( @phrases ) {
    if ( grep( /\b(En|En|A|À|Au|Le|Ce|Du|Au).+/, $cellule ) ) { # Si la cellule commence par l'expression régulière
        push( @entite, $cellule );
    }
}

foreach my $celplace ( @entite ) {

    #$cellieu = $cellieu.@dico
    @places = ( grep( /\b$cellieu/ . @topo );    #places = tableau des entités de lieu
}

foreach my $celtime ( @entite ) {
    @times = ( grep( /\b@entite.@tabtime/ ) );     #times = tableau des entité de temps
}

foreach my $entitetemps ( @times ) {
    $entitelieu = "<temps>.$entitetemps.</temps>";
}

foreach my $entitelieu ( @places ) {
    $entitelieu = "<lieu>.$entitetemps.</lieu>";

close( TEXT );

1 个答案:

答案 0 :(得分:1)

我怀疑只是在一个数组中找到任何东西,然后在另一个数组中找到任何东西就足够了。语言通常表现不佳,通常需要更多的工作来匹配真实的短语

但是,我可以直接回答您的问题。这只是将正则表达式模式构建为字符串然后编译它的问题

我使用了地点ABC,以及时刻XYZ。同 sprintfjoin我构建了一个表示单词边界的正则表达式,然后是第一个数组中的任何一个,然后是一些空格,然后是第二个数组中的任何一个,以及另一个单词边界

我希望这会有所帮助

use strict;
use warnings 'all';
use feature 'say';

chomp( my @data = <DATA> );

my @topo  = qw/ A B C /;
my @times = qw/ X Y Z /;

my $re = sprintf '\b(%s)\s+(%s)\b',
    join( '|', @topo ),
    join( '|', @times );

say "Regex: $re\n";  # Display the regex we've built

$re = qr/$re/i;      # Compile the regex with case-independence

say 'All Data';
say for @data;

say '---';

say 'Matching Data';
say for grep /$re/, @data;

__DATA__
R P G X
E U Q B
K B V X
R J Q X
B Y H V
R L E D
A C Y T
G B Z O
P B Z X
R C X J
Y P N I
U L E O
M C Z V
I R T X

输出

Regex: \b(A|B|C)\s+(X|Y|Z)\b

All Data
R P G X
E U Q B
K B V X
R J Q X
B Y H V
R L E D
A C Y T
G B Z O
P B Z X
R C X J
Y P N I
U L E O
M C Z V
I R T X
---
Matching Data
B Y H V
A C Y T
G B Z O
P B Z X
R C X J
M C Z V