【问题标题】:Splitting of Big File into Smaller Chunks in Shell Scripting在 Shell 脚本中将大文件拆分为较小的块
【发布时间】:2017-06-11 09:00:49
【问题描述】:

我需要使用 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/> 

“Pattern 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,因此非常耗时。

【问题讨论】:

  • “模式的最后一次出现”是什么意思?
  • 最后一次在文件中匹配模式。即模式“00003”在其第三个字段中匹配到 sample.txt 文件的第 5 行。所以进程想要将它拆分到第 5 行到一个单独的文件中。
  • 以后,请使用编辑框左上角的{}格式化工具对高亮文本进行格式化为代码/数据/输出。祝你好运。

标签: bash shell split csplit


【解决方案1】:

你可以试试 Perl:

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

并将其时间与其他解决方案进行比较...

编辑

将我的答案限制在您尚未尝试过的工具上……您也可以使用:

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

但我倾向于相信 perl 会更快。再次...我建议您自己测量不同解决方案的经过时间。

【讨论】:

  • @mklement0:我猜你在评论之前测试了这些“有缺陷的尝试”的性能......
  • 我认为您误解了,所以让我尝试以不同的方式解释它:OP 描述了一个问题,并在解决方案中包含了一个 尝试awk 命令)。这种尝试在技术上有缺陷,但更重要的是,它在概念上存在根本缺陷——即使修复了,这种尝试也无法解决问题。您的答案包含技术上正确的命令,相当于概念上有缺陷的尝试,因此不能解决 OP 的问题。
【解决方案2】:

不确定您是否会找到比awk 更快的工具,但这里有一个变体可以修复您自己的尝试,并且通过使用 string 匹配而不是 来加快速度正则表达式匹配。

它在循环中处理查找值,并将从上一次迭代停止的位置到当前值的最后次出现的所有内容输出到名为smallfile&lt;n&gt;的文件,其中&lt;n&gt;是以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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多