根据条件合并 csv 文件

根据条件合并 csv 文件

我有2个CSV每个日期的文件(csv_2014_4_15csv_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",如果为真则打印该行。

答案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 字段以去除时间。

相关内容