我有一个有趣的问题,我不太确定如何最好地解决,通过迭代列表。采用以下格式 -
element, date, unixTime, value
CZ, 12/27/2007 15:55, 1198788900, 42346
CZ, 12/27/2007 17:30, 1198794600, -10543
I, 12/27/2007 19:05, 1198800300, 4475
我想遍历每个唯一元素和每个日期,并获取“值”列的符号。例如,我想要 2007 年 12 月 27 日有 2 行,其中 CZ 和 I 各有一条。CZ 将为负值,因为当天最后部分发生的行具有负值,而 I 将为正值。然后对 12/28、12/29 等许多不同的元素再次执行此操作。我可以使用嵌套的 for 循环来迭代它,但它是一个巨大的文件,最好找到一种方法来迭代该文件,按日期排序,仅一次。我对如何最有效地做到这一点有点困惑。我不确定 bash 是否适合于此,或者其他一些语言(如 perl 或 python)是否适合。
答案1
让我们调用输入数据富:
echo 'element, date, unixTime, value
CZ, 12/27/2007 15:55, 1198788900, 42346
CZ, 12/27/2007 17:30, 1198794600, -10543
I, 12/27/2007 19:05, 1198800300, 4475' > foo
跑步GNU datamash
在富:
datamash -t, --header-in -g 1 last 4 < foo
输出:
CZ, -10543
I, 4475
更正式的开关名称datamash
可能会使上述内容更加清晰,而且我添加了标题名称(如果计算列不方便):
datamash --field-separator=',' --header-in --group=element last " value" < foo
答案2
假设 @agc 已正确解释了您所需的输出,则awk
可以使用普通旧版本。
awk -F, 'NR>1{a[$1]=$4}END{for(x in a){print x","a[x]}}' foo
CZ, -10543
I, 4475
答案3
您的文件已预先排序,这一事实使其易于使用sed
在任何给定时间点保存sed pattern space
不超过2 lines
.
sed -e '
$!{
N
/^\([^,]*\),[[:space:]]\{1,\}\([^[:space:]]\{1,\}\)[[:space:]].*[[:space:]]\([^[:space:]]\{1,\}\)\n\1,[[:space:]]\{1,\}\2[[:space:]]/D
}
s/^\([^,]*\),[[:space:]]\{1,\}\([^[:space:]]\{1,\}\)[[:space:]].*[[:space:]]\([^[:space:]]\{1,\}\)\(\n\)/\1 \3\4/
/\n/!s/^\([^,]*\),[[:space:]]\{1,\}\([^[:space:]]\{1,\}\)[[:space:]].*[[:space:]]\([^[:space:]]\{1,\}\)/\1 \3/
P;D
' yourfile
简短的
We always keep 2 lines in the pattern space and note the time when there
is a change in the 1st field. So long as we keep encountering the same
first two fields, we keep chopping off the previous line and reading in
the next. And on a transition we print the 1st and last fields of the
previous line, print it, remove upto the newline, and go back for more
with whats left in the pattern space.