在 bash 中使用两个 GNU Utils 和 Mac Utils
Using both GNU Utils with Mac Utils in bash
我正在绘制包含 N 个相关数据条目的超大文件。 (N 因文件而异)。
在这些文件中的每一个中,评论都会在文件的开头和结尾自动生成,并且希望在将它们重新组合成一个大数据集之前将其过滤掉。
不幸的是,我正在使用 MacOSx,在尝试删除文件的最后一行时遇到了一些问题。我读到最有效的方法是使用 head/tail bash 命令来截断数据部分。由于 head -n -1 不适用于 MacOSx 我不得不通过 homebrew 安装 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 合并的解决方法?
谢谢,
凯文
你的命令的问题是你再次为ghead
命令指定文件操作数,而不是让它从标准输入,通过管道;这导致 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 在评论中指出的那样,您可以 all 使用 sed
:
sed -n '9,$ {$!p;}' file
选项 -n
告诉 sed
仅在明确请求时才产生输出; 9,$
匹配从第 9
行到 (,
) 文件末尾(最后一行,$
)的所有内容,并且 {$!p;}
打印 (p
) 该范围内的每一行,除了 (!
) 最后 ($
).
我知道你的问题是关于使用 head
和 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=[=11=]}' inputfile
为了 "recognize" 最后一行,捕获前一行并在第 8 行之后打印,然后不打印最后一行,这有点不同。
这个 awk 解决方案有点 hack,就像 sed 解决方案一样,依赖于您只想删除文件的最后一行这一事实。
如果您想从文件底部剥离多于一行的行,您可能需要维护一个数组,该数组的功能类似于缓冲 FIFO 或滑动 window.
awk -v striptop=8 -v stripbottom=3 '
{ last[NR]=[=12=]; }
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
.
未禁止的所有内容
我正在绘制包含 N 个相关数据条目的超大文件。 (N 因文件而异)。
在这些文件中的每一个中,评论都会在文件的开头和结尾自动生成,并且希望在将它们重新组合成一个大数据集之前将其过滤掉。
不幸的是,我正在使用 MacOSx,在尝试删除文件的最后一行时遇到了一些问题。我读到最有效的方法是使用 head/tail bash 命令来截断数据部分。由于 head -n -1 不适用于 MacOSx 我不得不通过 homebrew 安装 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 合并的解决方法?
谢谢, 凯文
你的命令的问题是你再次为ghead
命令指定文件操作数,而不是让它从标准输入,通过管道;这导致 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 在评论中指出的那样,您可以 all 使用 sed
:
sed -n '9,$ {$!p;}' file
选项 -n
告诉 sed
仅在明确请求时才产生输出; 9,$
匹配从第 9
行到 (,
) 文件末尾(最后一行,$
)的所有内容,并且 {$!p;}
打印 (p
) 该范围内的每一行,除了 (!
) 最后 ($
).
我知道你的问题是关于使用 head
和 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=[=11=]}' inputfile
为了 "recognize" 最后一行,捕获前一行并在第 8 行之后打印,然后不打印最后一行,这有点不同。
这个 awk 解决方案有点 hack,就像 sed 解决方案一样,依赖于您只想删除文件的最后一行这一事实。
如果您想从文件底部剥离多于一行的行,您可能需要维护一个数组,该数组的功能类似于缓冲 FIFO 或滑动 window.
awk -v striptop=8 -v stripbottom=3 '
{ last[NR]=[=12=]; }
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
.