1

我正在绘制具有 N 个相关数据条目的超大文件。(N 因文件而异)。

在这些文件中的每一个中,都会在文件的开头和结尾自动生成注释,并希望在将它们重新组合成一个大数据集之前将它们过滤掉。

不幸的是,我使用的是 MacOSx,在尝试删除文件的最后一行时遇到了一些问题。我读过最有效的方法是使用 head/tail bash 命令来切断数据部分。由于 head -n -1 不适用于 MacOSx,我不得不通过自制软件安装 coreutils,其中 ghead 命令运行良好。然而命令,

tail -n+9 $COUNTER/test.csv | ghead -n -1 $COUNTER/test.csv  >> gfinal.csv

不起作用。一个不太令人满意的解决方法是我不得不分开命令,使用 ghead > newfile,然后在 newfile > gfinal 上使用 tail。不幸的是,这需要一段时间,因为我必须用第一个 ghead 编写一个新文件。

是否有将 GNU Utils 与标准 Mac Utils 结合的解决方法?

谢谢,凯文

4

2 回答 2

4

您的命令的问题是您再次为命令指定文件操作数,而不是让它通过管道从stdinghead获取输入;这会导致ghead忽略标准输入,因此第一个管道段被有效地忽略;只需省略ghead命令的文件操作数:

tail -n+9 "$COUNTER/test.csv" | ghead -n -1 >> gfinal.csv

也就是说,如果您只想删除最后一行,则不需要GNU head - OS X 自己的 BSDsed可以:

tail -n +9 "$COUNTER/test.csv" | sed '$d' >> gfinal.csv

$匹配最后一行,并d删除它(意味着它不会被输出)。

最后,正如@ghoti 在评论中指出的那样,您可以使用以下方法完成所有操作sed

sed -n '9,$ {$!p;}' file

选项-n告诉sed仅在明确要求时产生输出; 9,$匹配从行9到 ( ,) 文件末尾(最后一行,$)的所有内容,并{$!p;}打印 ( p) 该范围内的每一行,除了 ( !) 最后一行 ( $)。

于 2015-11-12T03:30:22.377 回答
2

我知道您的问题是关于使用headand tail,但我会回答,好像您对解决原始问题感兴趣,而不是弄清楚如何使用这些特定工​​具来解决问题。:)

一种使用方法sed

sed -e '1,8d;$d' inputfile

在这种简单程度下,GNU sed 和 BSD sed 的工作方式相同。我们的 sed 脚本说:

  • 1,8d- 删除第 1 到 8 行,
  • $d- 删除最后一行。

如果您决定即时生成这样的 sed 脚本,请注意您的引用;如果你把它放在双引号中,你将不得不转义美元符号。

另一种使用方法awk

awk 'NR>9{print last} NR>1{last=$0}' inputfile

这有点不同,以便“识别”最后一行,捕获前一行并在第 8 行之后打印,然后不打印最后一行。

这个 awk 解决方案有点像 sed 解决方案,依赖于您只想剥离文件的最后一行这一事实。

如果要从文件底部删除多于一行的行,则可能需要维护一个数组,该数组的功能类似于缓冲的 FIFO 或滑动窗口。

awk -v striptop=8 -v stripbottom=3 '
  { last[NR]=$0; }
  NR > striptop*2 { print last[NR-striptop]; }
  { delete last[NR-striptop]; }
  END { for(r in last){if(r<NR-stripbottom+1) print last[r];} }
' inputfile

您指定要去除多少变量。该last数组在内存中保留了许多行,从堆栈的远端打印,并在打印时删除它们。该END部分遍历数组中剩余的所有内容,并打印所有未被stripbottom.

于 2015-11-12T03:59:58.467 回答