![用awk分割文件时最后一行是错误的](https://linux22.com/image/48192/%E7%94%A8awk%E5%88%86%E5%89%B2%E6%96%87%E4%BB%B6%E6%97%B6%E6%9C%80%E5%90%8E%E4%B8%80%E8%A1%8C%E6%98%AF%E9%94%99%E8%AF%AF%E7%9A%84.png)
main.txt
我有一个如下所示的数据文件
20130826,aaaaaaaaaaaaaa,bbbbbbb
20130826,sdfasdfasdfas,sdfasdfasd
20130826,dfasdfas,asdf2323
...
20130827,sfasdfasdfasd,sdfasdfwea
我使用以下 awk 片段main.csv
按日期分割成较小的文件。
cat test01 | stdbuf -oL -eL awk -F',' '{print $2","$3 >> "data"$1".csv"; fflush()}'
我发现分割文件 data20130826.csv 的最后一行不完整,
...
20130826,dfasdfas,asdf2323
2013082
事实上,日期 20130826 的最后几行(10 左右)都丢失了,它们也不在 data20130827.csv 中。我尝试按照上面的行关闭缓冲,但这似乎没有帮助。我确信主文件没问题。出了什么问题?我正在使用 GNU Awk 4.0.1。
答案1
只是为了澄清我原来的帖子:我同意 Orion 的观点,并怀疑这是一个 awk 错误。我也不会为 fflush 烦恼。我认为这只是数据引起的 awk 问题。具体来说,我认为您可能有太多打开的文件描述符 - 文件中的每个日期都有一个。或者,您可能出于同样的原因达到了缓冲区限制 - 打开的文件太多。 fflush 不会关闭打开的文件 - 它只是刷新缓冲区。
那么输入文件中有多少个不同的日期?这就是您将有多少个打开的文件:
cut -d"," -f1 test01 | sort | uniq | wc -l
- 如果很多(数百个),那么请参阅我关于随时关闭文件的第二个建议。
两个建议:
1. 您确定数据只是纯文本,没有任何隐藏字符(如退格符)并且也具有正常的 UNIX 行结尾吗?你能 grep 出前缀为“20130826”的行来看看它们看起来正常并且实际上都是单独的行,即
cat test01 | grep "^20130826"
- and also run
cat test01 | grep -c "^20130826"
- 确认 grep 行数与输出文件中的内容匹配(或不匹配)
2.如果输入数据按日期顺序排序,那么您可以尝试在编写文件时关闭文件:自从我最初的帖子以来我对此进行了测试,它工作得很好:
cat test01 | awk -F"," '{prevfile=ofile; ofile=sprintf("data%s.csv",$1);
if (NR > 1 && ofile != prevfile) close(prevfile); print $2","$3 >> ofile}'
如果您的文件未按日期排序,此代码仍然有效,但会更频繁地打开和关闭文件。在这种情况下,只需在命令开头将“cat test01”更改为“sort test01”即可。
使用 awk 时,您并不总是需要显式关闭文件,但根据我的经验,如果您编写了很多这样的文件而不关闭其中任何一个文件,awk 就会崩溃,这可能仍然适用,因为我认为它与限制有关在打开的文件描述符上。
此外,当您附加到这些文件时,请确保在运行命令之前它们不包含任何数据。当事情不顺利时很容易忘记......
答案2
尝试:
$ cat test01 |
stdbuf -oL -eL awk -F',' '{print $2","$3 >> "data"$1".csv"; fflush("")}'
在 中gawk 4.0.1
,呼叫fflush()没有任何参数只刷新标准输出。您需要fflush()
使用空字符串进行调用""
才能awk
刷新所有打开的输出文件和管道。
使用gawk 4.0.2
和 以后,如果没有参数,或者参数为fflush()
空字符串""
,则awk
刷新所有打开的输出文件和管道的缓冲区。