我有一个 SQL 事实表,用于查找日期并返回另一个日期。
表格架构如下:
TABLE date_lookup
(
pk_date DATE,
plus1_months DATE,
plus2_months DATE,
plus3_months DATE
);
UNIQUE INDEX on date_lookup(pk_date);
我有一个加载文件(以竖线分隔),其中包含从 01-28-2012 到 03-31-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
按照上述规则为我的加载文件生成更多 2014 年 3 月 31 日之后的日期,或者我应该编写一个程序来完成此任务?
答案1
在这种情况下,我怀疑这sed
是否是适合这项工作的工具。我认为awk
如果您已经熟悉的话,您可能想使用awk
,否则,请编写一个程序。
我认识一位工程师,他使用sed
并awk
创建 MSC/NASTRAN 输入文件,其要求比您提到的还要严格,但他对这些工具非常熟悉,因此来自的神秘且无信息的错误消息并awk
没有困扰他。
如果您想使用 执行此操作awk
,我的建议是预处理输入以删除“-”和“|”人物。将程序写入awk
单独的文件中。使用文本字段位置($1、$2、$3...),并为输出编写 SQL INSERT 语句。这需要多次尝试,因此尽可能自动化。
答案2
虽然在技术上可以在 sed 中进行日期算术,但它根本不是适合这项工作的工具。使用 awk 或 perl 等内置整数运算的工具。
您的要求对于日期操作来说是不寻常的,因此如果您不想对日期算术进行硬编码,则需要一个丰富的日期操作库。珀尔的Date::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";
}