简短的

简短的

我有一个有趣的问题,我不太确定如何最好地解决,通过迭代列表。采用以下格式 -

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.

相关内容