![Можно ли использовать sed для создания загрузочного файла для моей таблицы фактов поиска дат?](https://rvso.com/image/23958/%D0%9C%D0%BE%D0%B6%D0%BD%D0%BE%20%D0%BB%D0%B8%20%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20sed%20%D0%B4%D0%BB%D1%8F%20%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F%20%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D1%87%D0%BD%D0%BE%D0%B3%D0%BE%20%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%20%D0%B4%D0%BB%D1%8F%20%D0%BC%D0%BE%D0%B5%D0%B9%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%8B%20%D1%84%D0%B0%D0%BA%D1%82%D0%BE%D0%B2%20%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0%20%D0%B4%D0%B0%D1%82%3F.png)
У меня есть таблица фактов SQL, которая используется для поиска даты и возврата другой даты.
Схема таблицы выглядит следующим образом:
TABLE date_lookup
(
pk_date DATE,
plus1_months DATE,
plus2_months DATE,
plus3_months DATE
);
UNIQUE INDEX on date_lookup(pk_date);
У меня есть загрузочный файл (разделенный вертикальной чертой), содержащий даты с 28.01.2012 по 31.03.2014.
Ниже приведен пример загрузочного файла:
01-28-2012|02-28-2012|03-28-2012|04-28-2012|
01-29-2012|02-29-2012|03-29-2012|04-29-2012|
01-30-2012|02-29-2012|03-30-2012|04-30-2012|
01-31-2012|02-29-2012|03-31-2012|04-30-2012|
...
03-31-2014|04-30-2014|05-31-2014|06-30-2014|
Правила для этой таблицы фактов следующие:
IF pk_date has more than 28 days in its month
AND plus1, plus2 or plus3_months only has 28, 29 or 30 days
THEN let plus1, plus2 or plus3 equal the last day of the following month.
У меня такой вопрос: возможно ли использовать его sed
для генерации большего количества дат после 31.03.2014, следуя приведенным выше правилам для моего файла загрузки, или мне следует написать программу для достижения этой цели?
решение1
Я сомневаюсь, что sed
это подходящий инструмент для работы, в данном случае. Я думаю, вы, вероятно, захотите использовать awk
, если вы уже знакомы с awk
, в противном случае напишите программу.
Я знал инженера, который использовал sed
и awk
для создания входных файлов MSC/NASTRAN, которые имели даже более строгие требования, чем те, о которых вы говорите, но он был достаточно хорошо знаком с этими инструментами, поэтому загадочные и неинформативные сообщения об ошибках от awk
его не беспокоили.
Если вы хотите сделать это с помощью awk
, я бы посоветовал вам предварительно обработать ввод, чтобы удалить символы '-' и '|'. Запишите программу awk
в отдельный файл. Используйте позиции текстовых полей ($1, $2, $3...) и напишите операторы SQL INSERT для вывода. Потребуется несколько попыток, поэтому автоматизируйте как можно больше.
решение2
Хотя технически возможно делать арифметику дат в sed, это совсем не тот инструмент для этой работы. Используйте инструмент вроде awk или perl, в котором встроена целочисленная арифметика.
Ваше требование необычно для манипуляций с датами, поэтому вам понадобится богатая библиотека для манипуляций с датами, если вы не хотите жестко кодировать арифметику дат. PerlDate::Manip
имеет такие функции, как Date_DaysInMonth
.
#!/usr/bin/env perl
use strict;
use warnings;
use Date::Manip;
use List::Util qw(/./);
sub shift_month {
my ($delta, $y, $m, $d) = @_;
$m += $delta;
$y += $m / 12;
$m %= 12;
return ($y, $m, min($d, Date_DaysInMonth($m, $y)));
}
my $next_day = ParseDateDelta("1 day");
my ($cur, $end) = (ParseDate($ARGV[0]), ParseDate($ARGV[1]));
while (Date_Cmp($cur, $end) < 0) {
my @ymd = UnixDate($cur, qw(%Y %m %d));
foreach my $i (0..3) {
printf "%02d-%04d-%02d|", @{[shift_month($i, @ymd)]}[1, 0, 2];
}
$cur = DateCalc($cur, $next_day);
print "\n";
}