目前,我们需要合并大量文件(多个GB文件)。现在,我已经编写了一个java代码来动态更新数据。令人遗憾的是,它的表现极低。由于我们提供的架构,我们不得不使用这个或bash脚本。我们不能安装任何软件包,所以csvtools也是遥不可及的。我们只能使用本机Ubuntu函数。
我们所拥有的:2 csv-具有未知模式的文件。我们只知道第一个条目总是ID,它是主键。两个比较过的文件本身总是有相同的模式。它需要用第二个文件更新旧条目,并插入不存在的KV。
示例1:
example1.csv
id|kv1|kv2|kv3|kv4|kv5|kv6|kv7|kv8|kv9|kv10|kv11
519712|3|57181|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519713|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519714|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000||2000-11-15 14:14:51.0000000example2.csv
id|kv1|kv2|kv3|kv4|kv5|kv6|kv7|kv8|kv9|kv10|kv11
519712|3|57181|5|"I changed value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519715|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519716|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000||2000-11-15 14:14:51.0000000预期产出:
id|kv1|kv2|kv3|kv4|kv5|kv6|kv7|kv8|kv9|kv10|kv11
519712|3|57181|5|"I changed value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519713|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519714|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000||2000-11-15 14:14:51.0000000
519715|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000||2000-11-15 14:16:51.0000000
519716|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000||2000-11-15 14:14:51.0000000示例2:
example1.csv
id|kv1|kv2|kv3|kv4|kv5|kv6|kv7|kv8|kv9|kv10
519712|3|57181|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519713|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519714|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000|2000-11-15 14:14:51.0000000example2.csv
id|kv1|kv2|kv3|kv4|kv5|kv6|kv7|kv8|kv9|kv10
519712|3|57181|5|"I changed value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519715|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519716|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000|2000-11-15 14:14:51.0000000预期产出:
id|kv1|kv2|kv3|kv4|kv5|kv6|kv7|kv8|kv9|kv10
519712|3|57181|5|"I changed value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519713|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519714|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000|2000-11-15 14:14:51.0000000
519715|3|57281|5|"another value"|"yay string"|||"another string"|2020-08-11 00:00:00.0000000|2000-11-15 14:16:51.0000000
519716|3|57481|5|"another value"|"yay string"|||"another string2"|2020-08-11 00:00:00.0000000|2000-11-15 14:14:51.0000000我已经试着适应这些主题:
例如,我的尝试:
join -a1 -j 1 -t"|" <(sort example1.csv | sort -b) <(sort example2.csv | sort -b) | sort -n但这件事出问题了。它将主键作为字符串来处理,而不是作为一个数值(这似乎是唯一的方法)
join --header --nocheck-order -j 1 -t"|" example1.csv example2.csv这是最“方便”的方法,因为它也忽略了头部,并将其打印到下一个文件。可悲的是0的结果。
join -j 1 -t"|" <(sed 1,1d example1.csv | sort --field-separator='|' -k 1b,1) <(sed 1,1d example2.csv | sort --field-separator='|' -k 1b,1)即使我明确指出,每件事都必须用数字来处理,但它也不起作用。
有什么想法吗?
诚挚的问候
发布于 2020-12-14 15:36:09
我自己解决的。由于ID始终是第一列,所以我将其用作黑名单。
# !/usr/bin/env bash
FILTER_TEMP_FILE=/PATH/blaa.temp
trap "{ rm -f $FILTER_TEMP_FILE; }" EXIT
NUM_COLUMNS=$(head -1 ${INPUTFILE} | sed 's/[^|]//g' | wc -c)
echo "Creating update-filter in ${FILTER_TEMP_FILE}"
OUTPUT_LAYOUT=1.1
for (( i=2; i <= $NUM_COLUMNS; ++i ))
do
OUTPUT_LAYOUT=$OUTPUT_LAYOUT',1.'$i
done在此之后,我使用它作为联合命令。
join -j 1 -t '|' -o $OUTPUT_LAYOUT <(sed 1,1d $1 | sort --temporary-directory=/tmp/ --field-separator='|' -k 1b,1) <(sed 1,1d $MERGEFILE | sort --temporary-directory=/tmp/ --field-separator='|' -k 1b,1) > ${FILTER_TEMP_FILE}
awk -F, '(NR==FNR){a[$INPUTFILE];next}!($INPUTFILE in a)' ${FILTER_TEMP_FILE} ${INPUTFILE} > ${OUTPUTFILE}
sed 1,1d ${MERGEFILE } >> ${OUTPUTFILE}
sort --temporary-directory=/tmp/ -n ${OUTPUTFILE} -o ${OUTPUTFILE}请注意,对于大型文件,它可能会出现问题。我需要重新调整它,使它只使用RAM (在我们的服务器上有大约250 G的RAM,但几乎没有任何tmp空间.(很讽刺)
https://stackoverflow.com/questions/65201831
复制相似问题