在bash中使用GNU Util和Mac Utils

时间:2015-11-12 03:25:10

标签: bash gnu-coreutils

我正在使用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上使用tail> gfinal。不幸的是,这需要一段时间,因为我必须用第一个ghead写一个新文件。

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

谢谢, 凯文

2 个答案:

答案 0 :(得分:4)

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

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

也就是说,如果您只想删除 last 行,则不需要 GNU head - OS X'自己的BSD sed将会:

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

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

最后,正如@ghoti在评论中指出的那样,您可以使用sed 所有进行操作:

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

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

答案 1 :(得分:2)

我意识到您的问题是关于使用headtail,但我会回答,好像您对解决原始问题感兴趣而不是弄清楚如何使用那些解决问题的特殊工具。 :)

使用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未禁止的所有内容。