将标头插入文件

时间:2011-05-12 15:07:42

标签: 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-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 

2 个答案:

答案 0 :(得分:12)

header="/name/of/file/containing/header"
for file in "$@"
do
    cat "$header" "$file" > /tmp/xx.$$
    mv /tmp/xx.$$ "$file"
done

您可能更喜欢将临时文件放在与您正在编辑的文件相同的文件系统上,但是任何需要在文件前面插入数据的内容最终都会非常接近于此。如果你每天都要这样做,那么你可能会把东西稍微装点一些,但是节省的几率可能是微不足道的(每个文件的分数为一秒)。

如果你真的,真的必须使用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行之前)的标题内容,然后其他所有内容都保持不变。这不像cat那样快。

使用awk的类似构造是:

header="/name/of/file/containing/header"
for file in "$@"
do
    awk '{print}' "$header" "$file" > /tmp/xx.$$
    mv /tmp/xx.$$ "$file"
done

这只是输出输出上的每个输入行;再次,不像cat那样迅速。

cat优于sedawk的另一个优势;即使大文件主要是二进制数据(它不知道文件的内容),cat也能正常工作。 sedawk都旨在处理分成行的数据;虽然现代版本可能会很好地处理二进制数据,但它并不是它们的设计目标。

答案 1 :(得分:1)

我使用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黑客,所以这可能是双加非优化的Perl代码。不过,它对我有用!