Это сложное требование, которое, как прокомментировал Гордон Линофф, было бы гораздо проще решить, если бы данные были уже правильно распределены.
Вот подход:
REGEXP_SUBSTR
и CONNECT BY
, чтобы разбить строку на строки, используя разделитель запятых REGEXP_SUBSTR
и разделителем пробела DENSE_RANK
и KEEP
, чтобы изолировать соответствующую строку Предполагая, что данные поступают из столбца str
в таблице my_table
:
WITH
cte0 AS (
SELECT TRIM(REGEXP_SUBSTR(str, '[^,]+', 1, LEVEL)) str
FROM my_table
CONNECT BY INSTR(str, ',', 1, LEVEL - 1) > 0
),
cte1 AS (
SELECT
TO_DATE(REGEXP_SUBSTR(str, '\S+', 1, 1), 'yyyy-mm-dd') dt,
REGEXP_SUBSTR(str, '\S+', 1, 2) val1,
REGEXP_SUBSTR(str, '\S+', 1, 3) val2
FROM cte0
ORDER BY 1 DESC
)
SELECT
MIN(dt) keep (dense_rank first order by dt) as dt,
MIN(val1) keep (dense_rank first order by dt) as val1,
MIN(val2) keep (dense_rank first order by dt) as val2
FROM cte1
WHERE dt > TO_DATE(?, 'yyyy-mm-dd')
... где ?
- дата ввода.
with
data as (
SELECT
'2015/04/01 11 GG, 2015/08/03 78 KK, 2012/12/12 44 TT, 2015/09/01 77 YY, 2015/09/01 88 ZZ' str
FROM DUAL
),
cte0 AS (
SELECT TRIM(REGEXP_SUBSTR(str, '[^,]+', 1, LEVEL)) str
FROM data
CONNECT BY INSTR(str, ',', 1, LEVEL - 1) > 0
),
cte1 AS (
SELECT
TO_DATE(REGEXP_SUBSTR(str, '\S+', 1, 1), 'yyyy-mm-dd') dt,
REGEXP_SUBSTR(str, '\S+', 1, 2) val1,
REGEXP_SUBSTR(str, '\S+', 1, 3) val2
FROM cte0
ORDER BY 1 DESC
)
SELECT
min(dt) keep (dense_rank first order by dt) as dt,
min(val1) keep (dense_rank first order by dt) as val1,
min(val2) keep (dense_rank first order by dt) as val2
FROM cte1
WHERE dt > TO_DATE('2015-08-01', 'yyyy-mm-dd')
-------------------------
DT | VAL1 | VAL2
:-------- | :--- | :---
03-AUG-15 | 78 | KK
Я сделал бы что-то вроде этого:
use File::Copy;
sub copy_recursively {
my ($from_dir, $to_dir, $regex) = @_;
opendir my($dh), $from_dir or die "Could not open dir '$from_dir': $!";
for my $entry (readdir $dh) {
next if $entry =~ /$regex/;
my $source = "$from_dir/$entry";
my $destination = "$to_dir/$entry";
if (-d $source) {
mkdir $destination or die "mkdir '$destination' failed: $!" if not -e $destination;
copy_recursively($source, $destination, $regex);
} else {
copy($source, $destination) or die "copy failed: $!";
}
}
closedir $dh;
return;
}
Другой опцией является File::Xcopy. Как имя говорит, оно более или менее эмулирует команду xcopy окон, включая ее фильтрацию и рекурсивные опции.
Из документации:
use File::Xcopy;
my $fx = new File::Xcopy;
$fx->from_dir("/from/dir");
$fx->to_dir("/to/dir");
$fx->fn_pat('(\.pl|\.txt)$'); # files with pl & txt extensions
$fx->param('s',1); # search recursively to sub dirs
$fx->param('verbose',1); # search recursively to sub dirs
$fx->param('log_file','/my/log/file.log');
my ($sr, $rr) = $fx->get_stat;
$fx->xcopy; # or
$fx->execute('copy');
# the same with short name
$fx->xcp("from_dir", "to_dir", "file_name_pattern");
Если Вы, оказывается, находитесь на подобной Unix ОС и имеете доступ к rsync (1)
, необходимо использовать это (например, через system()
).
File::Copy Perl немного повреждается (это не копирует полномочия в системах Unix, например), поэтому если Вы не хотите использовать свои системные инструменты, взгляд на CPAN. Возможно, File::Copy::Recursive мог быть полезным, но я не вижу, что любой исключает опции. Я надеюсь, что у кого-то еще есть лучшая идея.
Я не знаю, как сделать исключение с копией, но Вы могли обработать что-то вроде:
ls -R1 | grep -v <regex to exclude> | awk '{printf("cp %s /destination/path",$1)}' | /bin/sh
Классический ответ использовал бы'cpio -p
':
(cd $SOURCE_DIR; find . -type f -print) |
perl -ne 'print unless m/<regex-goes-here>/' |
cpio -pd $TARGET_DIR
'cpio
'управляйте соглашениями с фактическим копированием, включая сохранение разрешения. Прием'cd $SOURCE_DIR; find . ...
'соглашения с удалением ведущей роли источника соединяют каналом с имен. Единственная проблема с тем вызовом'find
'это, это не будет следовать за символьными ссылками; необходимо добавить'-follow
'если это - то, что Вы хотите.