Поблочное тестирование помогает много в проектах, которые больше, чем какой-либо разработчик может держать в их голове. Они позволяют Вам выполнять комплект модульного теста перед регистрацией и обнаруживать, повредили ли Вы что-то. Это сокращает партия на экземплярах необходимости находиться и вертеть Ваши ползунки при ожидании кого-то еще для исправления ошибки, в которой они зарегистрировались, или идущий в стычку возвращения их изменения, таким образом, можно получить некоторую сделанную работу. Это также очень ценно в рефакторинге, таким образом, можно быть уверены, что пересмотренный код проходит все тесты, которые сделал исходный код.
Использовать группировку с круглыми скобками и сохранять первую группу.
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
I prefer this:
my ( $table_name ) = $line =~ m/(\S{2}DT\S{3})/i;
This
$line
and captures the the text corresponding to the pattern 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.
Было бы лучше сопоставить шаблон, если он следует ОТ
. Я предполагаю, что имена таблиц состоят исключительно из букв 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 .
Родители позволят вам захватить часть регулярного выражения в специальные переменные: 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";
}
Используйте группу захвата:
$line =~ /(\S{2}DT\S{3})/i;
my $substr = $1;
$ &
содержит строку, соответствующую последнему совпадению с образцом.
Пример:
$str = "abcdefghijkl";
$str =~ m/cdefg/;
print $&;
# Output: "cdefg"
Таким образом, вы можете сделать что-то вроде
if($line =~m/ \S{2}DT\S{3}/i) {
print $&."\n";
}
Если вы используете $ &
в вашем коде замедлит все совпадения шаблонов.