2010-11-22 3 views
1

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

my @charpos=(); 
s/(?=([«»\n]))/push @charpos, [$1, 0+($-[0])]; "";/ge; 
# sort {$a->[1] <=> $b->[1]} @charpos; 

Но это решение использует «заменитель» оператор заменить с пустой строкой, это нормально? Должна ли прокомментированная строка быть раскоментирована?

+2

Это смешно, но мне, это выглядит как чудовищный и неэффективного регулярного выражения. – 2010-11-22 19:40:11

+0

Что вы действительно пытаетесь сделать? Получить список позиций (смещение символов), в которых в строке появляются каймы и строки (строки)? – 2010-11-22 19:42:22

+0

@ Джонатан Леффлер Я хочу заменить «« ... «...» ... «...» ... »` с `« ... »...« ... »...» ... »`, но за некоторыми исключениями: если уровень 1 закрыт guillemet отсутствует, то он должен быть оставлен как есть, то же самое, если уровень закрытия 1 уровня отсутствует в текущей строке. – ZyX 2010-11-22 19:48:19

ответ

2

Для вашей общей проблемы вы можете изучить sub parse_line в Text::ParseWords.

В контексте кода вы дали в вашем вопросе, я бы избежать изменения строки источника:

#!/usr/bin/perl 

use utf8; 
use strict; use warnings; 

my $x = q{«...«...»...«...»...»}; 

my @pos; 

while ($x =~ /([«»\n])/g) { 
    push @pos, $-[1]; 
} 

use YAML; 
print Dump \@pos; 
2

В общем, чтобы найти позиции символов в строке, вы можете сделать это следующим образом:

my $str = ...; 
my @pos; 
push @pos, pos $str while $str =~ /(?=[...])/g; 

И затем все позиции, где регулярное выражение совпавшие будет @pos. По крайней мере, с помощью этого метода вы не постоянно переписываете свою исходную строку.

+1

`pos` не возвращает позиции совпадений: * Возвращает смещение, где был остановлен последний« m // g »поиск * – 2010-11-22 20:01:26

2

Там больше чем один способ кожи кошки:

#!/usr/bin/env perl 

use 5.010; 
use utf8; 
use strict; 
use warnings qw< FATAL all >; 
use autodie; 
use open qw< :std OUT :utf8 >; 

END { close STDOUT } 

my @pos =(); 
my $string = q{«...«...»...«...»...»}; 
($string .= "\n") x= 3; 

say "string is:\n$string"; 

for ($string) { 
    push @pos, pos while m{ 
     (?= [«»\n]) 
    }sxg;; 
} 
say "first test matches \@ @pos"; 

@pos =(); 

## this smokes :) 
"ignify" while $string =~ m{ 
    [«»\n] 
    (?{ push @pos, $-[0] }) 
}gx; 
say "second test matches \@ @pos"; 

__END__ 
string is: 
«...«...»...«...»...» 
«...«...»...«...»...» 
«...«...»...«...»...» 

first test matches @ 0 4 8 12 16 20 21 22 26 30 34 38 42 43 44 48 52 56 60 64 65 
second test matches @ 0 4 8 12 16 20 21 22 26 30 34 38 42 43 44 48 52 56 60 64 65 

Но, пожалуйста, кредит Sinan.

0

Регулярное выражение для скитирования кошки, чтобы добавить в руководство. Является ли это чудовищное в глазах смотрящего:

use List::Util q/min/; 
my @targets = ('«','»',"\n"); 
my $x = q{«...«...»...«...»...»}; 
my $pos = min map { my $z = index($x,$_); $z<0?Inf:$z } @targets; 
my @pos; 
while ($pos < Inf) { 
    push @pos, $pos; 
    $pos = min map { my $z = index($x,$_,$pos+1); $z<0?Inf:$z } @targets; 
} 
Смежные вопросы