Regex Perl:使用正则表达式从文本中提取数据

Regex Perl:使用正则表达式从文本中提取数据,regex,perl,Regex,Perl,我正在使用Perl对正则表达式进行文本处理。我无法控制输入。我在下面展示了一些输入示例 正如您所看到的,项目B和C可以在字符串中使用不同的值n次。我需要得到所有的值作为反向参考。或者如果你知道另一种方式,我会洗耳恭听 我正在尝试使用分支重置模式(如中所述),但匹配字符串的运气不太好 ("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "D" 34896)(Int "E" 38046)) ("Data" (Int "A" 22)(Int "B" 1)(In

我正在使用Perl对正则表达式进行文本处理。我无法控制输入。我在下面展示了一些输入示例

正如您所看到的,项目B和C可以在字符串中使用不同的值n次。我需要得到所有的值作为反向参考。或者如果你知道另一种方式,我会洗耳恭听

我正在尝试使用分支重置模式(如中所述),但匹配字符串的运气不太好

("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "D" 34896)(Int "E" 38046)) ("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "B" 3)(Int "C" 4)(Int "B" 5)(Int "C" 6)(Int "D" 34896)(Int "E" 38046)) ("Data" (Int "A" 22)(Int "B" 22)(Int "C" 59)(Int "B" 1143)(Int "C" 1210)(Int "B" 1232)(Int "C" 34896)(Int "D" 34896)(Int "E" 38046))
我不确定将这些值作为反向引用会有什么好处——您希望由谁来处理重复键的情况(如第二行中的“C”)。此外,我不确定一旦提取,您希望对这些值执行什么操作

但我会从以下内容开始:

use Data::Dumper;

while (<DATA>)
{
    my @a = m!\(Int "(.*?)" ([0-9]+)\)!g;
    print Dumper(\@a);
}

__DATA__
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "D" 34896)(Int "E" 38046))
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "B" 3)(Int "C" 4)(Int "B" 5)(Int "C"     6)(Int "D" 34896)(Int "E" 38046)) 
("Data" (Int "A" 22)(Int "B" 22)(Int "C" 59)(Int "B" 1143)(Int "C" 1210)(Int "B" 1232)(Int "C" 34896)(Int "D" 34896)(Int "E" 38046))
使用数据::转储程序;
而()
{
我的@a=m!\(Int“(.*?”([0-9]+)\)!g;
打印转储程序(\@a);
}
__资料__
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“B”3)(Int“C”4)(Int“B”5)(Int“C”6)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”22)(Int“C”59)(Int“B”1143)(Int“C”1210)(Int“B”1232)(Int“C”34896)(Int“D”34896)(Int“E”38046))

这将为您提供一个重复键、值的数组。

我不确定将这些值作为反向引用会有什么好处-您希望由谁来处理重复键的情况(如第二行中的“C”)。此外,我不确定一旦提取,您希望对这些值执行什么操作

但我会从以下内容开始:

use Data::Dumper;

while (<DATA>)
{
    my @a = m!\(Int "(.*?)" ([0-9]+)\)!g;
    print Dumper(\@a);
}

__DATA__
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "D" 34896)(Int "E" 38046))
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "B" 3)(Int "C" 4)(Int "B" 5)(Int "C"     6)(Int "D" 34896)(Int "E" 38046)) 
("Data" (Int "A" 22)(Int "B" 22)(Int "C" 59)(Int "B" 1143)(Int "C" 1210)(Int "B" 1232)(Int "C" 34896)(Int "D" 34896)(Int "E" 38046))
使用数据::转储程序;
而()
{
我的@a=m!\(Int“(.*?”([0-9]+)\)!g;
打印转储程序(\@a);
}
__资料__
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“B”3)(Int“C”4)(Int“B”5)(Int“C”6)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”22)(Int“C”59)(Int“B”1143)(Int“C”1210)(Int“B”1232)(Int“C”34896)(Int“D”34896)(Int“E”38046))

这将为您提供一个重复键、值的数组。

我最初的想法是使用命名捕获并从
%-
获取值:

my $pattern = qr/
  \(
    "Data"\s+
    \(Int\s+"A"\s+(?<A>[0-9]+)\)
    (?:
      \(Int\s+"B"\s+(?<B>[0-9]+)\)
      \(Int\s+"C"\s+(?<C>[0-9]+)\)
    )+
    \(Int\s+"D"\s+(?<D>[0-9]+)\)
    \(Int\s+"E"\s+(?<E>[0-9]+)\)
  \)
/x;
最简单的方法是使用
m//g
。您可以按照Beano的建议捕获名称/值对,也可以使用多个模式捕获每个值:

my @b = m/Int "B" ([0-9]+)/g;
my @c = m/Int "C" ([0-9]+)/g;
# etc.

我最初的想法是使用命名捕获并从
%-
获取值:

my $pattern = qr/
  \(
    "Data"\s+
    \(Int\s+"A"\s+(?<A>[0-9]+)\)
    (?:
      \(Int\s+"B"\s+(?<B>[0-9]+)\)
      \(Int\s+"C"\s+(?<C>[0-9]+)\)
    )+
    \(Int\s+"D"\s+(?<D>[0-9]+)\)
    \(Int\s+"E"\s+(?<E>[0-9]+)\)
  \)
/x;
最简单的方法是使用
m//g
。您可以按照Beano的建议捕获名称/值对,也可以使用多个模式捕获每个值:

my @b = m/Int "B" ([0-9]+)/g;
my @c = m/Int "C" ([0-9]+)/g;
# etc.

不要尝试使用一个正则表达式一组正则表达式和拆分更容易理解:

#!/usr/bin/perl

use strict;
use warnings;

while (<DATA>) {
    next unless my ($data) = /\("Data" (.*)\)/;
    print "on line $., I saw:\n";
    for my $item ($data =~ /\((.*?)\)/g) {
        my ($type, $var, $num) = split " ", $item;
        print "\ttype $type var $var num $num\n";
    }
}

__DATA__
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "D" 34896)(Int "E" 38046))
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "B" 3)(Int "C" 4)(Int "B" 5)(Int "C" 6)(Int "D" 34896)(Int "E" 38046))
("Data" (Int "A" 22)(Int "B" 22)(Int "C" 59)(Int "B" 1143)(Int "C" 1210)(Int "B" 1232)(Int "C" 34896)(Int "D" 34896)(Int "E" 38046))
#/usr/bin/perl
严格使用;
使用警告;
而(){
下一步除非my($data)=/\(“data”(.*)\)/;
打印“在线$,我看到:\n”;
对于我的$item($data=~/\(.*)\)/g){
我的($type,$var,$num)=拆分的“$item;
打印“\t类型$type var$var num$num\n”;
}
}
__资料__
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“B”3)(Int“C”4)(Int“B”5)(Int“C”6)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”22)(Int“C”59)(Int“B”1143)(Int“C”1210)(Int“B”1232)(Int“C”34896)(Int“D”34896)(Int“E”38046))

如果数据可以跨行扩展,我建议使用解析器而不是正则表达式。

不要尝试使用一个正则表达式一组正则表达式和拆分更容易理解:

#!/usr/bin/perl

use strict;
use warnings;

while (<DATA>) {
    next unless my ($data) = /\("Data" (.*)\)/;
    print "on line $., I saw:\n";
    for my $item ($data =~ /\((.*?)\)/g) {
        my ($type, $var, $num) = split " ", $item;
        print "\ttype $type var $var num $num\n";
    }
}

__DATA__
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "D" 34896)(Int "E" 38046))
("Data" (Int "A" 22)(Int "B" 1)(Int "C" 2)(Int "B" 3)(Int "C" 4)(Int "B" 5)(Int "C" 6)(Int "D" 34896)(Int "E" 38046))
("Data" (Int "A" 22)(Int "B" 22)(Int "C" 59)(Int "B" 1143)(Int "C" 1210)(Int "B" 1232)(Int "C" 34896)(Int "D" 34896)(Int "E" 38046))
#/usr/bin/perl
严格使用;
使用警告;
而(){
下一步除非my($data)=/\(“data”(.*)\)/;
打印“在线$,我看到:\n”;
对于我的$item($data=~/\(.*)\)/g){
我的($type,$var,$num)=拆分的“$item;
打印“\t类型$type var$var num$num\n”;
}
}
__资料__
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”1)(Int“C”2)(Int“B”3)(Int“C”4)(Int“B”5)(Int“C”6)(Int“D”34896)(Int“E”38046))
(“数据”(Int“A”22)(Int“B”22)(Int“C”59)(Int“B”1143)(Int“C”1210)(Int“B”1232)(Int“C”34896)(Int“D”34896)(Int“E”38046))

如果您的数据可以跨行扩展,我建议使用解析器而不是正则表达式。

量化匹配中的捕获只返回最后一次捕获,这不是真正的错误或功能,只是它们的工作方式。据我所知,C#是唯一一个在量化匹配中多次捕获的实现。量化匹配中的捕获只返回最后一次捕获,这不是真正的bug或功能,只是它们的工作方式。据我所知,C#是唯一一个在量化匹配中多次捕获的实现。\d与Perl 5.8和5.10中的[0-9]不匹配;它匹配任何具有数字属性的UNICODE字符(包括“\x{1815}”,蒙古语数字5)。如果您的意思是[0-9],则必须使用[0-9]或字节pragma(但它将所有字符串转换为1字节字符,通常不是您想要的)。m的解释!!正则表达式。我倾向于使用“m!!”模式的形式与通常的“//”匹配,因为我必须比“!”更频繁地转义“/”字符性格您可以使用任何字符来分隔模式匹配(这也适用于sed)。正则表达式本身与字符(Int“”匹配,然后标记任何字符中最少的数字,后跟“”,然后标记一些数字,后跟“')。使用“g”扩展反复匹配,您就有了解决方案。如果这不能解释您的意图,请再次询问。关于将UNICODE字符与digit属性匹配的\d,而[0-9]与ASCII字符的特定范围匹配。我想在考虑这一点时,您需要记住您的输入数据将由什么组成——在上面的示例中,我假设了ASCII数据范围(我认为这是一个合理的假设),因为这说明了正则表达式的使用。我会想如果我的输入数据是Mon