在 Shell 脚本中将大文件拆分为较小的块
Splitting of Big File into Smaller Chunks in Shell Scripting
我需要使用 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"' '~pattern big_file' > smallfile
和 grep 命令,但它非常耗时,因为文件大小超过 300 MB。
您可以尝试使用 Perl:
perl -ne '/00003/ && print' big_file > small_file
并将其时间与其他解决方案进行比较...
编辑
我的回答仅限于您尚未尝试过的工具...您还可以使用:
sed -n '/00003/p' big_file > small_file
但我倾向于相信 perl 会更快。再次......我建议你自己测量不同解决方案的经过。
不确定您是否会找到比 awk
更快的工具,但这里有一个变体可以修复您自己的尝试,还可以通过使用 string[=33= 来稍微加快速度]匹配而不是正则表达式匹配。
它在一个循环中处理查找值,并将从前一次迭代停止的地方到最后一次手头值出现的所有内容输出到名为[=13=的文件中],其中 <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 ( != 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 ( != val[ndx]) {
if (p) { p=0; close(outFile); outFile="smallfile" ++ndx }
} else {
p=1
}
print > outFile
}
' big_file
我需要使用 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"' '~pattern big_file' > smallfile
和 grep 命令,但它非常耗时,因为文件大小超过 300 MB。
您可以尝试使用 Perl:
perl -ne '/00003/ && print' big_file > small_file
并将其时间与其他解决方案进行比较...
编辑
我的回答仅限于您尚未尝试过的工具...您还可以使用:
sed -n '/00003/p' big_file > small_file
但我倾向于相信 perl 会更快。再次......我建议你自己测量不同解决方案的经过。
不确定您是否会找到比 awk
更快的工具,但这里有一个变体可以修复您自己的尝试,还可以通过使用 string[=33= 来稍微加快速度]匹配而不是正则表达式匹配。
它在一个循环中处理查找值,并将从前一次迭代停止的地方到最后一次手头值出现的所有内容输出到名为[=13=的文件中],其中 <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 ( != 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 ( != val[ndx]) {
if (p) { p=0; close(outFile); outFile="smallfile" ++ndx }
} else {
p=1
}
print > outFile
}
' big_file