查找大写字母的运行

时间:2015-07-06 21:28:41

标签: regex perl perl5

我有一个文件,其中包含一些完全大写的单词和一些混合大小写的单词,我想提取完全大写的单词(包含在一行中) - 即由\b分隔并包含的内容至少两个大写字母,没有小写字母。一切都是7位。

因此,例如,如果一行是

The QUICK Brown fox JUMPs OV3R T4E LAZY DoG.

然后我想提取QUICKOV3R T4E LAZY

这是我到目前为止所做的:

while (<$fh>) { # file handle
    my @array = $_ =~ /\b[^a-z]*[A-Z][^a-z]*[A-Z][^a-z]*\b/;
    push @bigarray, @array;
}

有没有比[^a-z]*[A-Z][^a-z]*[A-Z][^a-z]*更优雅的方式?

3 个答案:

答案 0 :(得分:1)

看起来你想要所有的单词定义(构造\w)字符 要查找并允许至少两个大写字母而不是小写字母,您可能不会选择 绕过这个事实,他们必须任选地被帽子包围 和/或数字或下划线。

可能只是匹配你需要的东西。

\b[\d_]*[A-Z]+[\d_]*[A-Z]+[\d_]*\b

扩展:

 \b 
 [\d_]* 
 [A-Z]+ 
 [\d_]* 
 [A-Z]+ 
 [\d_]* 
 \b 

啊,结果

输入:

The QUICK Brown fox JUMPs OV3R T4E LAZY DoG.  

输出:

 **  Grp 0 -  ( pos 4 , len 5 ) 
QUICK  
-----
 **  Grp 0 -  ( pos 26 , len 4 ) 
OV3R  
-----
 **  Grp 0 -  ( pos 31 , len 3 ) 
T4E  
-----
 **  Grp 0 -  ( pos 35 , len 4 ) 
LAZY  

update - 如果要选择性地匹配由空格分隔的连续部分,
这会奏效。

 # (?&two_caps)(?:\s+(?&two_caps))*(?(DEFINE)(?<two_caps>\b[\d_]*[A-Z]+[\d_]*[A-Z]+[\d_]*\b))

 (?&two_caps) 
 (?:
      \s+ (?&two_caps) 
 )*

 (?(DEFINE)
      (?<two_caps>
           \b 
           [\d_]* 
           [A-Z]+ 
           [\d_]* 
           [A-Z]+ 
           [\d_]* 
           \b 
      )
 )

输出:

 **  Grp 0 -  ( pos 4 , len 5 ) 
QUICK  
 **  Grp 1 -  NULL 
---------
 **  Grp 0 -  ( pos 26 , len 13 ) 
OV3R T4E LAZY  
 **  Grp 1 -  NULL 

答案 1 :(得分:1)

如果你真的想要那些匹配的运行,可以使用带有零宽度断言的split,然后过滤结果:

while (<DATA>) {
    for my $e (split (/(?<=\b)([A-Z0-9_ ]+)(?=\b)/)){
        $e =~ s/^\s+|\s+$//g;
        print "$e\n" unless ($e =~/^$/ or $e =~ /.*[a-z]/);
    }
}

__DATA__
The QUICK Brown fox JUMPs OV3R T4E LAZY DoG.

打印:

QUICK
OV3R T4E LAZY

那么这是如何运作的?

split会将符合条件的部分与不符合条件的部分分开:

use Data::Dumper;

while (<DATA>) {
    print Dumper split (/(?<=\b)([A-Z0-9_ ]+)(?=\b)/); 
}

打印:

$VAR1 = 'The';
$VAR2 = ' QUICK ';
$VAR3 = 'Brown';
$VAR4 = ' ';
$VAR5 = 'fox';
$VAR6 = ' ';
$VAR7 = 'JUMPs';
$VAR8 = ' OV3R T4E LAZY ';
$VAR9 = 'DoG.';

然后循环遍历该数组,从每个元素中删除空格,并测试小写字符或空行。

这会导致一行为每行生成数组:

grep { $_ =~ /(?=[A-Z]{2,})^[^a-z]+$/ } map {s/^\s+|\s+$//g; $_} split (/(?<=\b)([A-Z0-9_ ]+)(?=\b)/);

答案 2 :(得分:0)

\b(?=\S*[A-Z]\S*[A-Z])[A-Z0-9]{2,}\b

试试这个。看看演示。

https://regex101.com/r/cK4iV0/24