разделить сначала от остальной части списка с помощью подстановки регулярных - PullRequest
0 голосов
/ 05 декабря 2011

Мне нужно разделить список между его первым элементом и остальными элементами, используя только подстановку регулярных выражений.

Списки элементов вводятся в виде строк, используя «##» в качестве разделителя, например:

''
'one'
'one##two'
'one##two##three'
'one##two words##three'

Моя попытка Perl на самом деле не работает:

my $sampleText = 'one##two words##three';
my $first = $sampleText;
my $rest = $sampleText;
$first =~ s/(.+?)(##.*)?/$1/g;
$rest =~ s/(.?+)(##)?(.*)/$3/g;
print "sampleText = '$sampleText', first = '$first', rest = '$rest'\n";

sampleText = 'one##two words##three', first = 'one', rest = 'ne##two words##three'

Обратите внимание на ограничения:

  • разделитель - многосимвольная строка
  • разрешены только подстановки регулярных выражений (1)
  • Я мог бы при необходимости "зацепить" подстановки регулярных выражений
  • Ожидаемый конечный результат - две строки: первый элемент и исходная строка спервый элемент обрезан (2)
  • список может содержать от 0 до n элементов, каждая из которых представляет собой любую строку, не содержащую разделитель.

(1) Я работаю с этим довольнобольшая Perl-система, где в какой-то момент списки элементов обрабатываются с использованием предоставленных операций.Одним из них является подстановка регулярных выражений.Ни один из других один не применим.Решение проблемы с использованием полного кода Perl легко, но это будет означать изменение системы, что не является вариантом, как в этот раз.

(2) контекст - это библиографический формат Unimarc, в котором авторы публикацииразделить на стандартные поля Unimarc 700 $ a для первого автора и 701 $ a для всех остальных авторов.

Ответы [ 5 ]

3 голосов
/ 05 декабря 2011

Что бы ни случилось с:

my ( $first, $rest ) = split /##/, $sampleText, 2;

3 голосов
/ 05 декабря 2011

Я предполагаю, что точка (1) означает, что вы не можете использовать встроенную функцию split? Было бы легко использовать дополнительный третий параметр split, который позволяет вам указать максимальное количество элементов.

my( $first, $rest ) = split( '##', $sampleText, 2 );

Но если это должно быть регулярное выражение, то вы почти правы, но использование .+? не сработает, когда нет sperators (потому что это просто займет первый символ. Это можно исправить, закрепив конец. Вместо этого что-то вроде:

my $sampleText = 'one##two words##three';
my $first = $sampleText;
my $rest = $sampleText;
$first =~ s/(.+?)(|##(.*))$/$1/g;
$rest  =~ s/(.+?)(|##(.*))$/$3/g;
print "sampleText = '$sampleText', first = '$first', rest = '$rest'\n";
0 голосов
/ 05 декабря 2011

Я должен соответствовать; не заменитель:

#!/usr/bin/env perl
use strict;
use warnings;
while (<DATA>) {
    chomp;
    m{([^#]*?)##(.*)} and print "[$1][$2]\n";
}
__DATA__
''
'one'
'one##two'
'one##two##three'
'one##two words##three'
0 голосов
/ 05 декабря 2011

Вы изменили квантификаторы ? и + во втором регулярном выражении, оно должно быть:

$rest =~ s/(.+?)(##)?(.*)/$3/g;
          ___^^

или более кратким:

$rest =~ s/.+?##(.*)/$1/;
0 голосов
/ 05 декабря 2011

try

 my ($first, $rest) = /(.+?)\#\#(.*)/;

// (или, m//) совпадает;Вам не нужно использовать s/// для замены.Он возвращает совпадения (здесь $first, $rest), или вы можете захватить их позже, используя $1, $2 и т. Д.

...