简体   繁体   English

Perl正则表达式匹配模式的多个实例并替换

[英]Perl regex match multiple instances of a pattern and replace

I have a string that looks like this: 我有一个看起来像这样的字符串:

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

I want to split this string into an array that consists of: 我想将此字符串拆分为包含以下内容的数组:

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

But splitting on the comment won't work so my next idea is to first replace the commas that reside between the square brackets with something else so I can split on the comma, then replace after the fact. 但是拆分注释不起作用,因此我的下一个想法是,先用其他东西替换方括号之间的逗号,以便我可以拆分逗号,然后在事实之后替换。

I've tried a few approaches with little success.. Any suggestions? 我尝试了几种方法,但收效甚微。

You can use look-ahead assertion in the pattern: 您可以在模式中使用先行断言:

my $s = "abc[1,2,3].something.here,foo[10,6,34].somethingelse.here,def[1,2].another";
my @a = split /,(?=\w+\[)/, $s;

When things get that complex, I like the parser approach. 当事情变得如此复杂时,我喜欢解析器方法。

#!/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;

Iterate through the characters in the string like this (pseudocode): 像这样遍历字符串中的字符(伪代码):

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

Sure, you could use regular expressions, but personally I rather aim for a simpler solution even if it's more hackish. 当然,您可以使用正则表达式,但就个人而言,我更希望寻求一个更简单的解决方案,即使该解决方案更加笨拙。 Regular expressions are a pain to read sometimes. 正则表达式有时很难读。

An alternative to eugene y's answer: eugene y的答案的替代方法:

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,"")

This question gave me excuse to take a look at Regexp::Grammars I wanted for some time. 这个问题让我借口看了我想要一段时间的Regexp :: Grammars Following snippet works for your input: 以下代码段可用于您的输入:

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",
# ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM