Perl提取文本

时间:2012-08-17 18:10:57

标签: regex perl search

我一直在研究这个问题! 我很感激你的帮助...

我的文档会是什么样的:

<text>
<text> command <+>= "stuff_i_need" <text>
<text>
<text> command <+>= stuff <text>
<text>
<text> command <+>= -stuff <text>
<text>
  • 任何带有缠绕括号的东西都是可选的
  • 东西可以是任何东西(苹果,橙子,香蕉),但它是我需要提取的东西
  • 命令已修复

到目前为止我的代码:

#!/usr/bin/env perl

use warnings;
use strict;
use Text::Diff;

# File Handlers 
open(my $ofh, '>in.txt');
open(my $ifh, '<out.txt');

while (<$ifh>)
{
    # Read in a line
    my $line = $_;
    chomp $line;

    # Extract stuff
    my $extraction = $line;

    if ($line =~ /command \+= /i) {        
        $extraction =~ s/.*"(.*)".*/$1/;
        # Write to file
        print $ofh "$extraction\n";
    }
}

5 个答案:

答案 0 :(得分:2)

基于示例输入:

 if ($line =~ /command\d*\s*\+?=\s*["-]?(\w+)"?/i) {    
    $extraction = $1; 
    print "$extraction\n";
 }   

答案 1 :(得分:2)

一些事情:

  1. 对于提取,请勿使用替换(即使用m//而不是s///)。如果您使用匹配项,匹配项中的括号内容组将作为列表返回(如果您愿意,还会分配到$1$2$3等。
  2. =~绑定您要匹配的变量。因此,您希望$extraction实际上是$line
  3. 您的.*匹配过于贪婪,会阻止匹配以您想要的方式取得成功。我的意思是“贪婪”,.*将匹配您的行中的尾随"。它将使用该行的其余输入,然后尝试匹配"并因为您已到达该行的末尾而失败。
  4. 您想指定单词可能是什么。例如,如果是字母,则匹配[a-zA-Z]

    my ($extraction) = $line =~ /command \+= "([a-zA-Z]*)"/;
    

    如果是数字,您需要[0-9]

    my ($extraction) = $line =~ /command \+= "([0-9]*)"/;
    

    如果它可以是"以外的任何内容,请使用[^"],这意味着“"以外的任何内容”:

    my ($extraction) = $line =~ /command \+= "([^"]*)"/;
    

    尝试匹配您正在寻找的内容而不是毯子.*通常会有所帮助。

答案 2 :(得分:1)

以下正则表达式可以帮助您:

m{
    (?<= = )        # Find an `=`
    \s*             # Match 0 or more whitespaces
    (?:             # Do not capture
        [ " \- ]    # Match either a `"` or a `-`
    )?              # Match once or never
    (               # Capture
        [^ " \s ]+  # Match anything but a `"` or a whitespace
    )
}x;

答案 3 :(得分:0)

以下单行将提取一个单词(一个没有空格的字符序列),该单词后面带有一个前缀为可选加号的等号,由可选引号括起。它将从in.txt读取并写入out.txt

perl -lne 'push @a, $1 if /command\s*\+?=\s*("?\S+"?)/ }{ 
    print for @a' in.txt > out.txt

完整代码 - 如果您更喜欢脚本形式 - 是:

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    push @a, $1 if /command\s*\+?=\s*("?\S+"?)/;
}
{
    print $_ foreach (@a);
}

the O module的Deparse功能提供。

答案 4 :(得分:0)

轻量级解决方案。

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

open my $ifh, '<','in.txt';
open my $ofh, '>', 'out.txt';

while (<$ifh>)
{
    if (/
        \s command\s\+?=\s
        (?:-|("))?     # The word can be preceded by an optional - or "
        (\w+)
        (?(1)\1)\s+    # If the word is preceded by a " it must be end 
                       # with a "
        /x)
    {
        print $ofh $2."\n";
    }
}