如何以模式将大文件分为两部分?
举个例子file.txt:
ABC
EFG
XYZ
HIJ
KNL
我想这个文件在拆分XYZ,使得file1包含排队到XYZ休息的线条file2。
如何以模式将大文件分为两部分?
举个例子file.txt:
ABC
EFG
XYZ
HIJ
KNL
我想这个文件在拆分XYZ,使得file1包含排队到XYZ休息的线条file2。
Answers:
有了awk您就可以做到:
awk '{print >out}; /XYZ/{out="file2"}' out=file1 largefile
说明:第一个awk参数(out=file1)定义了一个变量,其文件名将在largefile处理后续参数()时用于输出。该awk程序将打印所有行于由变量指定的文件out({print >out})。如果XYZ将找到模式,则将重新定义输出变量以指向新文件({out="file2}"),该文件将用作打印后续数据行的目标。
参考文献:
这是一项工作csplit:
csplit -sf file -n 1 large_file /XYZ/
将silently分割文件,创建与前片f九file和n使用一个单一的数字umbered,如file0等。注意,使用/regex/起来会拆分,但不包括行匹配regex。要分割并包括行匹配,请regex添加一个+1偏移量:
csplit -sf file -n 1 large_file /XYZ/+1
这将创建两个文件 file0和file1。如果您绝对需要为它们命名file1,则file2可以始终在csplit命令中添加一个空模式并删除第一个文件:
csplit -sf file -n 1 large_file // /XYZ/+1
创建file0,file1以及file2但是file0是空的,所以你可以放心地将其删除:
rm -f file0
对于现代ksh版本sed,这是上述sed基础答案之一的shell变体(即,不带):
{ read in <##XYZ ; print "$in" ; cat >file2 ;} <largefile >file1
还有一个ksh单独的变体(即也省略了cat):
{ read in <##XYZ ; print "$in" ; { read <##"" ;} >file2 ;} <largefile >file1
(纯ksh解决方案似乎性能很好;在2.4 GB的测试文件上,它需要19-21秒,而使用sed/ cat方法则需要39-47秒)。
awk您的基准测试表现如何?虽然我敢肯定,ksh将有可能永远赢得这场战斗,如果你使用的是GNU sed你不是很公平sed- GNU的-unbuffered是小便穷人的办法,以确保POSIXLY描述符的偏移留在程序中退出,其中,它-应该没有必要减慢程序的正常运行-缓冲很好-所有sed要做的就是完成后查找描述符。无论出于什么原因,GNU都会扭转这种想法。
while;作为<##重定向操作符的定义副作用,隐式完成了打印。并且只有匹配的行需要打印。(这样,shell功能实现对于包括incl./excl。的支持最为灵活。)while我希望显式循环会明显慢一些(但尚未检查)。
head而不是read; 看起来似乎有点慢,但这是更简短的代码:{ head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3。
尝试使用GNU sed:
sed -n -e '1,/XYZ/w file1' -e '/XYZ/,${/XYZ/d;w file2' -e '}' large_file
sed -e '1,/XYZ/{w file1' -e 'd}' large_file > file2
一个简单的技巧是根据目标图案是否匹配,将其打印到STDOUT或STDERR。然后,您可以使用外壳程序的重定向运算符相应地重定向输出。例如,在Perl中,假设调用了输入文件,并且假定f了两个输出文件f1和f2:
丢弃与拆分模式匹配的行:
perl -ne 'if(/XYZ/){$a=1; next} ; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2包括匹配的行:
perl -ne '$a=1 if /XYZ/; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2或者,打印到不同的文件句柄:
丢弃与拆分模式匹配的行:
perl -ne 'BEGIN{open($fh1,">","f1");open($fh2,">","f2");}
if(/XYZ/){$a=1; next}$a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
包括匹配的行:
perl -ne 'BEGIN{open($fh1,">","f1"); open($fh2,">","f2");}
$a=1 if /XYZ/; $a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
XYZ行是否应包含在输出中?