Unix 将头插入文件
我想听听您如何将标题行(一个文件中的所有行)插入到另一个文件(更大,几GB)中的说明。我更喜欢Unix/awk/sed方式来完成这项工作Unix 将头插入文件,unix,header,insert,awk,Unix,Header,Insert,Awk,我想听听您如何将标题行(一个文件中的所有行)插入到另一个文件(更大,几GB)中的说明。我更喜欢Unix/awk/sed方式来完成这项工作 # header I need to insert to another, they are in a file named "header". ##fileformat=VCFv4.0 ##fileDate=20090805 ##source=myImputationProgramV3.1 ##reference=1000GenomesPilot-NCB
# header I need to insert to another, they are in a file named "header".
##fileformat=VCFv4.0
##fileDate=20090805
##source=myImputationProgramV3.1
##reference=1000GenomesPilot-NCBI36
##phasing=partial
##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of Samples With Data">
##INFO=<ID=DP,Number=1,Type=Integer,Description="Total Depth">
##INFO=<ID=AF,Number=.,Type=Float,Description="Allele Frequency">
##INFO=<ID=AA,Number=1,Type=String,Description="Ancestral Allele">
##INFO=<ID=DB,Number=0,Type=Flag,Description="dbSNP membership, build 129">
##INFO=<ID=H2,Number=0,Type=Flag,Description="HapMap2 membership">
##FILTER=<ID=q10,Description="Quality below 10">
##FILTER=<ID=s50,Description="Less than 50% of samples have data">
##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
##FORMAT=<ID=GQ,Number=1,Type=Integer,Description="Genotype Quality">
##FORMAT=<ID=DP,Number=1,Type=Integer,Description="Read Depth">
##FORMAT=<ID=HQ,Number=2,Type=Integer,Description="Haplotype Quality">
#CHROM POS ID REF ALT QUAL FILTER INFO
#头我需要插入另一个,它们位于名为“头”的文件中。
##fileformat=VCFv4.0
##fileDate=20090805
##来源=我的插补程序v3.1
##参考=1000GenomesPilot-NCBI36
##相位=部分
##信息=
##信息=
##信息=
##信息=
##信息=
##信息=
##滤器=
##滤器=
##格式=
##格式=
##格式=
##格式=
#色度位置ID参考高度质量过滤器信息
您可能更愿意将临时文件定位在与正在编辑的文件相同的文件系统上,但任何需要在文件前面插入数据的操作最终都会非常接近这一点。如果你打算每天整日都这样做,你可能会组装一些更光滑的东西,但节省的可能性很小(每个文件只有几分之一秒)
如果您确实必须使用sed
,那么我想您可以使用:
header="/name/of/file/containing/header"
for file in "$@"
do
sed -e "0r $header" "$file" > /tmp/xx.$$
mv /tmp/xx.$$ "$file"
done
该命令读取第0行之后(第1行之前)的标题“after”的内容,然后所有其他内容都会原封不动地通过。但这并不像猫那样迅速
使用awk的类似构造为:
header="/name/of/file/containing/header"
for file in "$@"
do
awk '{print}' "$header" "$file" > /tmp/xx.$$
mv /tmp/xx.$$ "$file"
done
这只是在输出上打印每个输入行;同样,速度不如cat
快
与
sed
或awk
相比,cat
还有一个优点cat
即使大文件主要是二进制数据也能工作(它不知道文件的内容)。sed
和awk
都设计用于处理拆分成行的数据;虽然现代版本甚至可以很好地处理二进制数据,但这并不是它们的设计初衷 我用一个Perl脚本完成了这一切,因为我必须遍历目录树并以不同的方式处理各种文件类型。基本剧本是
#!perl -w
process_directory(".");
sub process_directory {
my $dir = shift;
opendir DIR, $dir or die "$dir: not a directory\n";
my @files = readdir DIR;
closedir DIR;
foreach(@files) {
next if(/^\./ or /bin/ or /obj/); # ignore some directories
if(-d "$dir/$_") {
process_directory("$dir/$_");
} else {
fix_file("$dir/$_");
}
}
}
sub fix_file {
my $file = shift;
open SRC, $file or die "Can't open $file\n";
my $file = "$file-f";
open FIX, ">$fix" or die "Can't open $fix\n";
print FIX <<EOT;
-- Text to insert
EOT
while(<SRC>) {
print FIX;
}
close SRC;
close FIX;
my $oldfile = $file;
$oldFile =~ s/(.*)\.\(\w+)$/$1-old.$2/;
if(rename $file, $oldFile) {
rename $fix, $file;
}
}
#!perl-w
进程目录(“.”);
子进程目录{
我的$dir=shift;
opendir、$DIR或die“$DIR:不是目录\n”;
my@files=readdir;
closedir;
foreach(@files){
下一个if(/^\./或/bin/或/obj/);#忽略一些目录
如果(-d“$dir/$\”){
进程目录(“$dir/$”);
}否则{
修复文件(“$dir/$”);
}
}
}
子修复文件{
我的$file=shift;
打开SRC,$file或die“无法打开$file\n”;
my$file=“$file-f”;
打开修复程序“>$FIX”或die“无法打开$FIX\n”;
一路打印修复,在文件开头插入导致所有后续字节移位,这意味着所有文件块都可能被更改。这是一个很酷的答案。我从你的指导中学到了很多。非常感谢。@Jonathan,我还需要在现有的大文件中添加标题行。在我的情况下,标题行对应于数字存储在bash变量中的。如何使用awk/sed
来执行此操作?我做了如下操作:awk-v param1=“$param1”-v param2=“$param2”'开始{print“description1”;print param1“param2”;print“description2”}{print}test data>${tmpFile}
。在大于2GB的文件中,我遇到以下错误:awk:无法打开test.data(值对于定义的数据类型来说太大)
。您对如何处理大文件有什么建议吗?@Javier:如果您的awk
在处理大文件(>2GB)时遇到问题,那么可能是时候升级一些东西了-可能是awk
。要替换所描述的参数,您需要做更多的工作。请参阅的答案以查看文件中变量的单向处理。@Jonathan,谢谢!我最近在linux
().我使用的是Ubuntu10.04 64位
,最近安装的11.04 32位
。而awk
使用的是10.04
版本中的大文件(>2GB
),我没有遇到任何问题。这似乎就是我出现这些问题的原因。你认为,可能是这样吗?我也在尝试发现11.04 64位
版本有多稳定。@jianfeng.mao:“非常感谢”我刚刚开始学习Unix shell/sed/awk/perl来做生物信息学。我还没有测试你的脚本。但是,非常感谢你的好意。
#!perl -w
process_directory(".");
sub process_directory {
my $dir = shift;
opendir DIR, $dir or die "$dir: not a directory\n";
my @files = readdir DIR;
closedir DIR;
foreach(@files) {
next if(/^\./ or /bin/ or /obj/); # ignore some directories
if(-d "$dir/$_") {
process_directory("$dir/$_");
} else {
fix_file("$dir/$_");
}
}
}
sub fix_file {
my $file = shift;
open SRC, $file or die "Can't open $file\n";
my $file = "$file-f";
open FIX, ">$fix" or die "Can't open $fix\n";
print FIX <<EOT;
-- Text to insert
EOT
while(<SRC>) {
print FIX;
}
close SRC;
close FIX;
my $oldfile = $file;
$oldFile =~ s/(.*)\.\(\w+)$/$1-old.$2/;
if(rename $file, $oldFile) {
rename $fix, $file;
}
}