В Perl, как я могу получить подобранную подстроку от regex?

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

10
задан brian d foy 16 July 2009 в 17:30
поделиться

6 ответов

Использовать группировку с круглыми скобками и сохранять первую группу.

if( $line =~ /(\S{2}DT\S{3})/i )
{
  my $substring = $1;
}

Приведенный выше код устраняет непосредственную проблему извлечения имени первой таблицы. Однако вопрос также спрашивал, как вытащить все имена таблиц. Итак:

# FROM\s+     match FROM followed by one or more spaces
# (.+?)       match (non-greedy) and capture any character until...
# (?:x|y)     match x OR y - next 2 matches
# [^,]\s+[^,] match non-comma, 1 or more spaces, and non-comma
# \s*;        match 0 or more spaces followed by a semi colon
if( $line =~ /FROM\s+(.+?)(?:[^,]\s+[^,]|\s*;)/i )
{
  # $1 will be table1, table2, table3
  my @tables = split(/\s*,\s*/, $1);
  # delim is a space/comma
  foreach(@tables)
  {
     # $_ = table name
     print $_ . "\n";
  }
}

Результат:

Если $ line = "SELECT * FROM AADTTAB, BBDTTAB;"

Вывод:

AADTTAB
BBDTTAB

Если $ line = "SELECT * FROM AADTTAB;"

Вывод:

AADTTAB

Версия Perl: v5.10.0 для MSWin32-x86-multi-thread

20
ответ дан 3 December 2019 в 13:20
поделиться

I prefer this:

my ( $table_name ) = $line =~ m/(\S{2}DT\S{3})/i;

This

  1. scans $line and captures the the text corresponding to the pattern
  2. returns "all" the captures (1) to the "list" on the other side.

This psuedo-list context is how we catch the first item in a list. It's done the same way as parameters passed to a subroutine.

my ( $first, $second, @rest ) = @_;


my ( $first_capture, $second_capture, @others ) = $feldman =~ /$some_pattern/;

NOTE:: That said, your regex assumes too much about the text to be useful in more than a handful of situations. Not capturing any table name that doesn't have dt as in positions 3 and 4 out of 7? It's good enough for 1) quick-and-dirty, 2) if you're okay with limited applicability.

17
ответ дан 3 December 2019 в 13:20
поделиться

Было бы лучше сопоставить шаблон, если он следует ОТ . Я предполагаю, что имена таблиц состоят исключительно из букв ASCII. В таком случае лучше сказать то, что вы хотите. С учетом этих двух замечаний, обратите внимание, что успешный захват совпадения регулярного выражения в контексте списка возвращает совпадающие подстроки.

#!/usr/bin/perl

use strict;
use warnings;

my $s = 'select * from aadttab, bbdttab';
if ( my ($table) = $s =~ /FROM ([A-Z]{2}DT[A-Z]{3})/i ) {
    print $table, "\n";
}
__END__

Вывод:

C:\Temp> s
aadttab

В зависимости от версии perl в вашей системе , вы можете использовать именованную группу захвата, которая может упростить чтение:

if ( $s =~ /FROM (?<table>[A-Z]{2}DT[A-Z]{3})/i ) {
    print $+{table}, "\n";
}

См. perldoc perlre .

8
ответ дан 3 December 2019 в 13:20
поделиться

Родители позволят вам захватить часть регулярного выражения в специальные переменные: 1 доллар, 2 доллара, 3 доллара ... Итак:

$line = ' abc andtabl 1234';
if($line =~m/ (\S{2}DT\S{3})/i)   {   
    # here I wish to get (only) substring that match to pattern \S{2}DT\S{3}    
    # (7 letter table name) and display it.      
    print $1."\n";
}
7
ответ дан 3 December 2019 в 13:20
поделиться

Используйте группу захвата:

$line =~ /(\S{2}DT\S{3})/i;
my $substr = $1;
3
ответ дан 3 December 2019 в 13:20
поделиться

$ & содержит строку, соответствующую последнему совпадению с образцом.

Пример:

$str = "abcdefghijkl";
$str =~ m/cdefg/;
print $&;
# Output: "cdefg"

Таким образом, вы можете сделать что-то вроде

if($line =~m/ \S{2}DT\S{3}/i) {
    print $&."\n";
}

ПРЕДУПРЕЖДЕНИЕ:

Если вы используете $ & в вашем коде замедлит все совпадения шаблонов.

-1
ответ дан 3 December 2019 в 13:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: