分割出一个大文件

时间:2018-08-22 15:41:43

标签: bash awk sed

我想使用以下行处理200 GB的文件:

...
{"captureTime": "1534303617.738","ua": "..."}
...

目标是将此文件拆分为按小时分组的多个文件。

这是我的基本脚本:

#!/bin/sh

echo "Splitting files"

echo "Total lines"
sed -n '$=' $1

echo "First Date"
head -n1 $1 | jq '.captureTime' | xargs -i date -d '@{}' '+%Y%m%d%H'

echo "Last Date"
tail -n1 $1 | jq '.captureTime' | xargs -i date -d '@{}' '+%Y%m%d%H'

while read p; do
  date=$(echo "$p" | sed 's/{"captureTime": "//' | sed 's/","ua":.*//' | xargs -i date -d '@{}' '+%Y%m%d%H')
  echo $p >> split.$date
done <$1 

一些事实:

  • 要处理的80000000行
  • jq不能正常工作,因为某些JSON行无效。

您能帮助我优化此bash脚本吗?

谢谢

2 个答案:

答案 0 :(得分:3)

这个awk解决方案可能会助您一臂之力:

awk -F'"' '{file=strftime("%Y%m%d%H",$4); print >> file; close(file) }' $1

它实际上替代了您的while循环。

此外,您可以将完整的脚本替换为:

# Start AWK file
BEGIN{ FS='"' }
(NR==1){tmin=tmax=$4}
($4 > tmax) { tmax = $4 }
($4 < tmin) { tmin = $4 }
{ file="split."strftime("%Y%m%d%H",$4); print >> file; close(file) }
END {
  print "Total lines processed: ", NR
  print "First date: "strftime("%Y%m%d%H",tmin)
  print "Last date:  "strftime("%Y%m%d%H",tmax)
}

随后您可以运行为:

awk -f <awk_file.awk> <jq-file>

注意:strftime的使用表明您需要使用GNU awk。

答案 1 :(得分:2)

您可以通过更改此选项开始优化 sed 's/{"captureTime": "//' | sed 's/","ua":.*//' 有了这个 sed -nE 's/(\{"captureTime": ")([0-9\.]+)(.*)/\2/p'

  

-n禁止自动打印图案空间

     

-E在脚本中使用扩展的正则表达式