Как извлечь текст между двумя шаблонами с помощью REGEX Perl - PullRequest
5 голосов
/ 04 июня 2011

В следующих строках я могу сохранить строки между " Описание: " и " Tag: " в переменной с использованием REGEX PERL и какой тип данных будет хорошим для использования , строка или список или что-то еще?

(Я пытаюсь написать программу на Perl для извлечения информации из текстового файла с информацией о пакете Debian и преобразования ее в файл RDF (OWL) (онтология).)

Описание: библиотека для декодирования потоков ATSC A / 52 (разработка) liba52 - бесплатная библиотека для декодирования потоков ATSC A / 52. Стандарт A / 52 является используется в различных приложениях, включая цифровое телевидение и DVD. это также известный как AC-3.

Этот пакет содержит файлы для разработки. Домашняя страница: http://liba52.sourceforge.net/

Tag: devel :: library, role :: devel-lib

Код, который я написал до сих пор:

#!/usr/bin/perl
open(DEB,"Packages");
open(ONT,">>debianmodelling.txt");

$i=0;
while(my $line = <DEB>)
{

    if($line =~ /Package/)
    {
        $line =~ s/Package: //;
        print ONT '  <package rdf:ID="instance'.$i.'">';
        print ONT    '    <name rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</name>'."\n";
    }
elsif($line =~ /Priority/)
{
    $line =~ s/Priority: //;
    print ONT '    <priority rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</priority>'."\n";
}

elsif($line =~ /Section/)
{
    $line =~ s/Section: //;
    print ONT '    <Section rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</Section>'."\n";
}

elsif($line =~ /Maintainer/)
{
    $line =~ s/Maintainer: //;
    print ONT '    <maintainer rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</maintainer>'."\n";
}

elsif($line =~ /Architecture/)
{
    $line =~ s/Architecture: //;
    print ONT '    <architecture rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</architecture>'."\n";
}
elsif($line =~ /Version/)
{
    $line =~ s/Version: //;
    print ONT '    <version rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</version>'."\n";
}
elsif($line =~ /Provides/)
{
    $line =~ s/Provides: //;
    print ONT '    <provides rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</provides>'."\n";
}
elsif($line =~ /Depends/)
{
    $line =~ s/Depends: //;
    print ONT '    <depends rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</depends>'."\n";
}
elsif($line =~ /Suggests/)
{
    $line =~ s/Suggests: //;
    print ONT '    <suggests rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</suggests>'."\n";
}

elsif($line =~ /Description/)
{
    $line =~ s/Description: //;
    print ONT '    <Description rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</Description>'."\n";
}
elsif($line =~ /Tag/)
{
    $line =~ s/Tag: //;
    print ONT '    <Tag rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'.$line.'</Tag>'."\n";
    print ONT '  </Package>'."\n\n";
}
$i=$i+1;
}

Ответы [ 3 ]

17 голосов
/ 04 июня 2011
my $desc = "Description:";
my $tag  = "Tag:";

$line =~ /$desc(.*?)$tag/;
my $matched = $1;
print $matched;

или


my $desc = "Description:";
my $tag  = "Tag:";

my @matched = $line =~ /$desc(.*?)$tag/;
print $matched[0];

или


my $desc = "Description:";
my $tag  = "Tag:";

(my $matched = $line) =~ s/$desc(.*?)$tag/$1/;
print $matched;

Дополнительный


Если ваше описание и тег могут находиться в отдельных строках, вам может понадобиться использовать модификатор /s, чтобы рассматривать его как одну строку, чтобы \n не разрушил его. Пример:

$_=qq{Description:foo 
      more description on 
      new line Tag: some
      tag};
s/Description:(.*?)Tag:/$1/s; #notice the trailing slash
print;
4 голосов
/ 04 июня 2011

Предполагая:

my $example; # holds the example text above

Вы можете:

(my $result=$example)=~s/^.*?\n(Description:)/$1/s; # strip up to first marker

$result=~s/(\nTag:[^\n]*\n).+$/$1/s; # strip everything after second marker line

Или

(my $result=$example)=~s/^.*?\n(Description:.+?Tag:[^\n]*\n).*$/$1/s;

Оба предполагают, что значение Tag: содержится в одной строке.1010 *

Если это не так, вы можете попробовать:

(my $result=$example)=~s/
    (                        # start capture
        Description:         # literal 'Description:'
        .+?                  # any chars (non-greedy) up to
        Tag:                 # literal 'Tag:'
        .+?                  # any chars up to
    )
    (?:                      # either
      \n[A-Z][a-z]+\:        #  another tagged value name 
    |                         # or
      $                       #  end of string
    )
/$1/sx;
3 голосов
/ 04 июня 2011

Я считаю, что проблема вызвана использованием цикла чтения строки для данных, структурированных по абзацам. Если вы можете сохранить файл в памяти и применить split с захваченным разделителем, обработка будет намного более плавной:

#!/usr/bin/perl -w

use strict;
use diagnostics;
use warnings;

use English;

# simple sample sub
my $printhead = sub {
  printf "%5s got the tag '%s ...'\n", '', substr( shift, 0, 30 );
};
# map keys/tags? to functions
my %tagsoups = (
    'PackageName' => sub {printf "%5s got the name '%s'\n", '', shift;}
  , 'Description' => sub {printf "%5s got the description:\n---------\n%s\n----------\n", '', shift;}
  , 'Tag'         => $printhead
);
# slurp Packages (fallback: parse using $INPUT_RECORD_SEPARATOR = "Package:")
open my $fh, "<", './Packages-00.txt' or die $!;
local $/; # enable localized slurp mode
my $all = <$fh>;
my @pks = split /^(Package):\s+/ms, $all;
close $fh;
# outer loop: Packages
for (my $p = 1, my $n = 0; $p < scalar @pks; $p +=2) {
  my $blk = "PackageName: " . $pks[$p + 1];
  my @inf = split /\s*^([\w-]+):\s+/ms, $blk;
  printf "%3d %s named %s\n", ++$n, $pks[$p], $inf[ 2 ];
  # outer loop: key-value-pairs (or whatever they are called)
  for (my $x = 1; $x < scalar @inf; $x += 2) {
      if (exists($tagsoups{$inf[ $x ]})) {
          $tagsoups{$inf[ $x ]}($inf[$x + 1]);
      }
  }
}

вывод для сокращенного файла Packages из моей Ubuntu Linux:

  3 Package named abrowser-3.5-branding
      got the PackageName:
---------
abrowser-3.5-branding
----------
      got the Description:
---------
dummy upgrade package for firefox-3.5 -> firefox
 This is a transitional package so firefox-3.5 users get firefox on
 upgrades. It can be safely removed.
----------
  4 Package named casper
      got the PackageName:
---------
casper
----------
      got the Description:
---------
Run a "live" preinstalled system from read-only media
----------
      got the Tag:
---------
admin::boot, admin::filesystem, implemented-in::shell, protocol::smb, role::plugin, scope::utility, special::c
ompletely-tagged, works-with-format::iso9660
----------

Использование хэша для функций, применяемых к извлеченным частям, сохранит детали создания XML из циклов синтаксического анализатора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...