我有2个CSV每个日期的文件(csv_2014_4_15和csv_2014_4_16),具有基本结构和几个独特的列,如下所示。
id,name,created_at,updated_at,other columns
12, joe, 2013-1-1 18:30, 2014-2-1 12:00
56, bob, datetime, datetime
我想根据这些条件合并 2 个 csv 文件。到目前为止我的代码如下。
if (csv_date_x.id == csv_date_x+1.id)
{
if(csv_date_x.updated_at < csv_date_x.updated_at)
add csv_date_x+1 row into out.csv
}
else {
if(csv_date_x+1.created_at == TODAY (yyyy-mm-dd)
add csv_date_x+1 row into out.csv
}
答案1
尝试这个:
$ awk -F',' -v t="$(date +"%Y-%-m-%-d")" '
FNR == NR {
u[$1] = $4;
next;
}
$4 > u[$1] {
print;
next;
}
t ~ $3
' file_1 file_2
解释
- 我们得到今天的日期,将其保存在变量中
t
- 在读取 file_1 时
FNR == NR
,我们将每个 id 的每次更新时间保存在关联数组中u
,key 是 id,value 是更新时间。 读取 file_2 时:
- 如果 id 的更新日期
$4
大于数组u
($4 > u[$1]
) 中保存的相应 id 更新时间,则打印该行并跳到下一行。 - 如果上述条件为假,我们检查当前行的创建日期是否是今天,
t ~ $3
即"2014-7-11" ~ "2014-7-11 12:00"
,如果为真则打印该行。
- 如果 id 的更新日期
答案2
我假设 csv_date_x 表示 csv_2014_4_15,而 csv_date_x+1 表示 csv_2014_4_16。但根据您的伪代码,您从不使用 csv_date_x 中的任何行,因此这更像是一个过滤器而不是合并,并且您最终得到 csv_2014_4_16 的子集。
这是一项不平凡的编程任务,但我可以为您指出一个有利可图的方向。
如果您必须处理前两个字段中的转义逗号,这种事情可能会变得很棘手。我假设你不这样做。
我还假设您可以逐行比较这两个文件,因为您没有指定。
您需要首先规范化 csv 文件,以便月份和日期始终为两位数(前导零)。然后可以对它们进行文本比较,这对于awk
.就像是:
sed 's/-\([1-9]\)/-0\1/'
(这假设您的名称、ID 或“其他列”中没有连字符,如果是这样,您将需要不同的方法,可能会更仔细地匹配日期模式,并可能限制为第三和第四字段)。
使用该date
程序以与您的字段匹配的输出格式生成今天的日期,并将其作为变量传递以供awk
使用:
awk -v Today=$(date +"%Y-%m-%d %H:%M") -v File1=csv_2014_4_15 -v File2=csv_2014_4_16 '
{ getline line1 < File1;
getline line2 < File2;
split(line1, f1, ",");
split(line2, f2, ",");
}
f1[1] == f2[1] { ...; next } # compare IDs this is your first 'if' clause
{ ... } # this is your else clause since the previous ended with "next"
那时你的状态非常好。 f1 包含文件 1 中的行的字段,f2 包含文件 2 中的行的字段。您可以比较 ID(例如 f1[1] 和 f2[1])和日期(例如 f1[2] 用于创建 f1[3] 用于更新)。并打印你想要的行。您可以Today
与今天的日期进行比较。
awk
请注意,您可以通过拆分第三个和第四个字段来变得更漂亮,并在其中进行日期格式标准化-
,但我发现sed
首先通过会更容易。
另请注意,今天包含日期和时间。如果您只想比较日期,可以将其从date
命令规范中删除,但您还需要在比较之前拆分 csv 字段以去除时间。