Perl - проблема с "]" в регулярном выражении - PullRequest
1 голос
/ 15 марта 2019

У меня есть строка:

my $string = "name_of_my_function(arg1,arg2,[arg3,arg4])";

и я хочу извлечь имя функции "name_of_my_function" и параметры:

$arg1 = "arg1"
$arg2 = "arg2"
@arg_list = ("arg3", "arg4")

код, который я использую для извлечения функции:

$row =~ m/^([^\(]*)\(([^\)]*)\)/;
$function = $1;

Однако, это работает, когда строка не имеет "]", например:

my $string = "name_of_my_function(arg1,arg2,arg3)";

но ничего не возвращается, когда есть "]"

Есть идеи?

Спасибо

SLP

Ответы [ 2 ]

4 голосов
/ 15 марта 2019

Регулярное выражение, которое вы показываете, фиксирует имя функции и все остальные аргументы в строке, что является очень разумным первым шагом.Затем разберите аргументы из этой второй строки.Я расширяю ваш $string, чтобы иметь несколько списков аргументов в скобках, чередующихся с не заключенными в скобки

perl -wE'
    $s = "name_of_my_function(arg1,arg2,[arg3,arg4],arg5,[arg6,arg7])"; 
    @m = $s =~ /^([^\(]*)\(([^\)]*)\)/; 
    @p = grep { $_ } split /\s*,\s*|\[(.*?)\]/, $m[1];
    for (@p) { 
        if (/,/) { push @arg_list, $_ }
        else     { push @args, $_ }
    }
    say $m[0];
    say for @args; 
    say for @arg_list
'

Это печатает

name_of_my_function
arg1
arg2
arg5
arg3,arg4
arg6,arg7

split - это место, где находятся отдельные аргументыизвлеченные, а также списки аргументов в квадратных скобках, каждый в виде строки.Это может вернуть пустые элементы, таким образом grep { $_ }, чтобы отфильтровать их.

Затем вы можете приступить к извлечению отдельных аргументов из списков, которые были в скобках, снова разделив каждую строку в @arg_list на ,.


Основная часть вышеприведенного может , поскольку проблема стоит, в одной инструкции

@p = grep { $_ } split /\( | \) | \[(.*?)\] |,/x, $s;

, где я добавил модификатор /x, чтобы иметь возможность разметить его для удобства чтения.Это доставляет @p имя функции, отдельные аргументы и строку со списком аргументов (через запятую) из каждого [].

Однако я думаю, что гораздо разумнее разбить это нанесколько шагов.

2 голосов
/ 15 марта 2019

Что ж, если количество аргументов является переменным, это не так просто сделать с помощью только rgex (аргументы будут сопоставлены с квантификатором +, поэтому они не будут сохранены в группе захвата, что было бы легкоизвлекать).Учитывая вышесказанное, вы можете использовать этот шаблон (\w+)\(((\w+|\[(\w+,?)+\]),?)+\)

Объяснение:

(\w+) - сопоставить один или несколько символов слова (имя функции) и сохранить его при первом захватегруппа,

(\w+|\[(\w+,?)+\]) - чередование: совпадение \w+ (то же, что и выше) или \[(\w+,?)+\]: \[ - буквальное совпадение [, (\w+,?)+ - совпадение или более раз \w+,шаблон, представляющий собой один или несколько символов слова, за которыми следуют одна или ноль запятых (,?), \] - буквально ],

((\w+|\[(\w+,?)+\]),?)+ - соответствует целому шаблону выше, за которым может следовать запятая (,?) один или несколько раз.Это будет соответствовать списку аргументов.

\(, \) 0 match (, ) буквально

Дальнейшая обработка - извлекать то, что заключено в скобки (), чтобы извлечь аргументысоставить список программно - было бы проще сделать это со сложным регулярным выражением

Demo

UPDATE :

Попробуйте шаблон:https://regex101.com/r/wBcJZ0/3

Я пропустил объяснение, так как оно очень похоже на предыдущий шаблон.

Обновленная демка

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