2017-01-26 53 views
1

我需要根据大文件中使用shell脚本最后一次出现的模式将较大的文件拆分成更小的块。例如。在shell脚本中将大文件拆分成小块在

Sample.txt的

NORTH EAST|0004|00001|Fost|Weaather|<br/> 
NORTH EAST|0004|00001|Fost|Weaather|<br/> 
SOUTH|0003|00003|Haet|Summer|<br/> 
SOUTH|0003|00003|Haet|Summer|<br/> 
SOUTH|0003|00003|Haet|Summer|<br/> 
EAST|0007|00016|uytr|kert|<br/> 
EAST|0007|00016|uytr|kert|<br/> 
WEST|0002|00112|WERT|fersg|<br/> 
WEST|0002|00112|WERT|fersg|<br/> 
SOUTHWEST|3456|01134|GDFSG|EWRER|<br/> 

“模式1 = 00003”将要搜索的输出文件必须包含sample_00003.txt(文件将基于要在其上被搜索图案的第三字段排序)

NORTH EAST|0004|00001|Fost|Weaather|<br/> 
NORTH EAST|0004|00001|Fost|Weaather|<br/> 
SOUTH|0003|00003|Haet|Summer|<br/> 
SOUTH|0003|00003|Haet|Summer|<br/> 
SOUTH|0003|00003|Haet|Summer|<br/> 

“Pattren 2 = 00112” 将要搜索的输出文件必须包含sample_00112.txt

EAST|0007|00016|uytr|kert|<br/> 
EAST|0007|00016|uytr|kert|<br/> 
WEST|0002|00112|WERT|fersg|<br/> 
WEST|0002|00112|WERT|fersg|<br/> 

使用

awk -F'|' -v 'pattern="00003"' '$3~pattern big_file' > smallfile 

和grep命令,但它是非常耗时,因为文件是300 + MB的大小。

+0

你所说的“最后一次出现的意思是的模式“? – codeforester

+0

模式在文件中匹配的最后时间。 I.e模式“00003”在第三个字段中匹配sample.txt文件的第5行。所以进程想把它分割出来,直到第5行成为一个单独的文件。 – Katchy

+1

将来,请使用突出显示的文本编辑框左上方的格式化工具将其格式化为代码/数据/输出。 祝你好运。 – shellter

回答

2

不知道你是否会比awk找到一个更快的工具,但在这里,修复自己的尝试,也是一个变种利用字符串匹配而不是正则表达式匹配速度的东西了一点。

它处理在一个循环中查找值,并且输出一切从先前迭代通过最后发生值的离开的地方在手到名为smallfile<n>文件,其中<n>是开始1的索引。

ndx=0; fromRow=1 
for val in '00003' '00112' '|'; do # 2 sample values to match, plus dummy value 
    chunkFile="smallfile$((++ndx))" 
    fromRow=$(awk -F'|' -v fromRow="$fromRow" -v outFile="$chunkFile" -v val="$val" ' 
    NR < fromRow { next } 
    { if ($3 != val) { if (p) { print NR; exit } } else { p=1 } } { print > outFile } 
    ' big_file) 
done 

需要注意的是虚值|确保最后一个真正的价值相匹配后的任何剩余行保存到块文件了。


注意,移动所有的逻辑放到一个awk脚本要快很多,因为big_file将只需要读取一次

awk -F'|' -v vals='00003|00112' ' 
    BEGIN { split(vals, val); outFile="smallfile" ++ndx } 
    { 
    if ($3 != val[ndx]) { 
     if (p) { p=0; close(outFile); outFile="smallfile" ++ndx } 
    } else { 
     p=1 
    } 
    print > outFile 
    } 
' big_file 
0

你可以用Perl尝试:

perl -ne '/00003/ && print' big_file > small_file 

,并与其他解决方案,比较其定时...

编辑

限制我的回答对你没有尝试已的工具...你也可以使用:

sed -n '/00003/p' big_file > small_file 

但我倾向于认为perl会更快。再次...我建议你自己衡量不同解决方案的使用时间。

+0

@ mklement0:我想你在评论之前测试了这些“有缺陷的尝试”的性能...... – mauro

+0

我想你误解了,所以让我尝试以不同的方式解释它:OP描述了一个问题,并在解决方案中包含了_attempt_ 'awk'命令)。 这种尝试在技术上有缺陷,但更重要的是,它在概念上有点基本上存在缺陷 - 即使是固定的,这种尝试也不能解决问题。 您的答案中包含_technically_正确的命令,它与概念上有缺陷的尝试相同,因此不解决OP的问题。 – mklement0

相关问题