2016-04-27 49 views
0

我有一个4.5GB的测试文件,我正在尝试格式化它。使用sed格式化大文件

首先,我试图用','替换选项卡,并用"分隔每个列字段。

其次我用awk和sed格式化文件中的日期字段。

这里是我使用的是什么:

对于格式:

cat test_sample.csv | sed -e 's/"/""/g' | sed -e 's/\t/","/g' | sed -e 's/$/"/g' | sed -e 's/^/"/' > test_sample.csv 

对于日期:

awk 'BEGIN{FS=OFS="\",\""} NR>1{cmd = "date -d \"" $10 "\" \"+%Y-%m-%d\"";cmd | getline out; $10=out; close("uuidgen")} 1' test_sample.csv > _report.tmp && mv _report.tmp test_sample.csv 

这些命令运行过程中出现的小文件罚款,但都失败,并清除所有文件中的数据。

请有人可以帮我格式化此文件吗?

+0

你有(或者你可以安装)GNU awk的时间函数吗? –

+0

您可能不需要调用日期和getline,因此您的脚本可能更有效。如果您编辑您的问题以包含简洁,可测试的样本输入和预期输出,我们可以为您提供帮助。实际上,在这一点上,你可能希望把它作为一个单独的后续问题,因为你已经接受了这个答案。 –

回答

5

它们还清除小文件,因为重定向首先发生,所以文件被截断并保持为空。

考虑:

$ cat file.txt 
A line of text 
$ cat file.txt > file.txt 
$ cat file.txt  # Empty! 

为了避免这种情况,你必须复制到一个临时文件–这在sed的-i选项为你做。它可以选择扩展:

sed -i.bak '...' 

这解决了您的文件截断问题。

至于其他:

  • 不叫sed的很多次这样的:

    sed 's/pattern1/replacement1/' file | sed 's/pattern2/replacement2/' | ... 
    

    这通过完整的文件,也适用于每一个命令,制作过程要慢得多。改为:

    sed 's/pattern1/replacement1/;s/pattern2/replacement2/...' 
    

    只处理一次文件。

  • 您不必使用cat来管道入sed:sed将文件名作为参数,您可以避免这种情况Useless Use of cat。如果组合命令并避开所有管道,更是如此,请参见下文。
  • 不要将sed和awk结合在一起。作为一个经验法则,如果你在任何地方使用awk,你不需要sed。

的组合单通就地sed命令可能看起来像这样:

sed -i 's/"/""/g;s/\t/","/g;s/$/"/;s/^/"/' test_sample.csv 

,减少一切到一个awk命令(而不是一个班轮友好下去,但绝对比合并sed和awk)速度快:

awk 'BEGIN { OFS="," } 
NR > 1 { 
    gsub(/"/, "\"\"") 
    for (i = 1; i <= NF; ++i) 
     $i = "\"" $i "\"" 
    cmd = "date -d \"" $10 "\" \"+%Y-%m-%d\"" 
    cmd | getline out 
    $10 = out 
    close("uuidgen") 
    print 
}' test_sample.csv > _report.tmp && mv _report.tmp test_sample.csv 

在Mac OS中找到的BSD sed需要-i''

+0

虽然我同意你所有的答案,但我不认为sed的管道输出到另一个会产生太多的开销,与使用';'链接它们相比。既然在这两种情况下,sed都会将线条放回到模式空间中以对其进行修改。 –

+1

@jaypalsingh如果每行都有替换(管道和使用';'不是很大的区别),或者整个文件中只有很少的部分(由于多次处理整个文件导致大量的开销),它是有区别的,所以我想说有些情况他们是相似的,有些地方管道速度较慢,但​​没有一个管道速度更快的地方 - 为什么不把它作为总是使用速度更快的习惯。 –

+1

对,我并不是说管道会更快,只是不太确定这是否会使事情大幅下降。我个人不喜欢管道,所以我不能抱怨。 ':)'应该解决OP问题的所有好建议。 –