2015-07-06 3 views
3

У меня есть файл, содержащий некоторые слова с заглавной буквы и некоторые слова смешанного слова, и я хочу извлечь полностью заглавные пробеги слов (содержащихся в одной строке), то есть вещи, разделенные \b и содержащий не менее двух заглавных букв и не строчных букв. Все 7 бит.Найти пробежки заглавных букв

Так, например, если линия

The QUICK Brown fox JUMPs OV3R T4E LAZY DoG. 

, то я хочу, чтобы извлечь QUICK и OV3R 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]*?

+0

последовательных столиц, или 2+ столиц где-нибудь в слове. например 'CApital' или' cApiTal'? последовательный - это легко. 2+ в любом месте, не так много. –

+0

@MarcB последовательный. Но также включая другие символы '\ w', но не строчные буквы. – JQKP

+0

«другие символы' \ w', но без строчных букв »- номера и символы подчеркивания? –

ответ

1

Похоже, вы хотите, чтобы все определения слов (конструкция \w) были символами.
Чтобы найти и разрешить как минимум два колпачка и ни одного нижнего регистра, вы, вероятно, не собираетесь
обойти тот факт, что они должны быть дополнительно окружены колпачками
и или цифрами или символом подчеркивания.

Возможно, просто соответствует тому, что вам нужно.

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

Expanded:

\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 

обновление - Если вы хотите дополнительно матч последовательных частей, разделенных пробелами,
это будет работать.

# (?&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 
+0

+1 для вас, потому что я * думаю * это точно отвечает на вопрос, поскольку он появился до 49 секунд, прежде чем вы разместили это. За 49 секунд до того, как вы разместили это сообщение, я исправил ошибку в вопросе, и этот ответ неправильно ответил на вопрос. – JQKP

1

Если вы действительно хотите запустить из этих матчей, возможно, использовать раскол с нулевой шириной утверждений, а затем отфильтровать результаты:

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)/); 
+0

Это интересно, я использовал много вещей, используя Perl. Используется много разделов и дальнейших циклов для выполнения того, что будет делать одно регулярное выражение. Я думаю, что это просто паранойя регулярного выражения. Слишком много разговоров о регулярном выражении - boogyman .. во всяком случае, не знаю. – sln

+0

Я люблю регулярное выражение. Не бугиман вообще. В этом случае мне было просто разумнее ... – dawg