Perl регулярное выражение сопоставить несколько экземпляров шаблона и заменить - PullRequest
2 голосов
/ 18 марта 2011

У меня есть строка, которая выглядит следующим образом:

abc[1,2,3].something.here,foo[10,6,34].somethingelse.here,def[1,2].another

Я хочу разбить эту строку на массив, который состоит из:

abc[1,2,3].something.here
foo[10,6,34].somethingelse.here
def[1,2].another

Но разделение на комментарий выиграл 'Это не так, моя следующая идея - сначала заменить запятые, которые находятся между квадратными скобками, на что-то еще, чтобы я мог разделить запятую, а затем заменить на факт.

Я пробовал несколько подходов с небольшимуспех .. Есть предложения?

Ответы [ 5 ]

4 голосов
/ 18 марта 2011

Вы можете использовать прогнозное утверждение в шаблоне:

my $s = "abc[1,2,3].something.here,foo[10,6,34].somethingelse.here,def[1,2].another";
my @a = split /,(?=\w+\[)/, $s;
1 голос
/ 18 марта 2011

Когда все становится так сложно, мне нравится парсерный подход.

#!/usr/bin/perl
use strict;
use warnings;

my $statement  =  "abc[1,2,3].something.here,foo[10,6,34].somethingelse.here,def[1,2].another";

my $index      = qr/\[(?:\d+)(?:,\d+)*\]/;
my $variable   = qr/\w+$index?/;
my $expression = qr/$variable(?:\.$variable)*/;

my @expressions = ($statement =~ /($expression)/g);

print "$_\n" for @expressions;
0 голосов
/ 18 марта 2011

Этот вопрос дал мне повод взглянуть на Regexp :: Grammars Я хотел некоторое время.Следующий фрагмент работает для вашего ввода:

use Regexp::Grammars;
use Data::Dump qw(dd);

my $input
    = 'abc[1,2,3].something.here,foo[10,6,34].somethingelse.here,def[1,2].another';

my $re = qr{
    <[tokens]> ** (,)  # comma separated tokens

    <rule: tokens>     <.token>*
    <rule: token>      \w+ | [.] | <bracketed>
    <rule: bracketed>  \[ <.token> ** (,) \]
}x;

dd $/{tokens}
    if $input =~ $re;

# prints
# [
#   "abc[1,2,3].something.here",
#   "foo[10,6,34].somethingelse.here",
#   "def[1,2].another",
# ]
0 голосов
/ 18 марта 2011

Альтернатива ответу Евгения У:

my $s = "abc[1,2,3].something.here,foo[10,6,34].somethingelse.here,def[1,2].another";
my @a = ($s =~ /[^,]+\[[\d,]*\]/g);
print join("\n", @a,"")
0 голосов
/ 18 марта 2011

Перебирать символы в строке следующим образом (псевдокод):

found_closing_bracket = 0;
buffer = ''
array = []

foreach c in str:

   if c == ']'
      found_closing_bracket = 1

   if c == ',' && found_closing_bracket == 1
     push(array, buffer)
     buffer = ''
     found_closing_bracket = 0

   else
     buffer = buffer + c

Конечно, вы можете использовать регулярные выражения, но лично я скорее стремлюсь к более простому решению, даже если оно более хакерское. Регулярные выражения иногда трудно читать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...