我想听听您关于如何将标题行(文件中的所有行)插入另一个文件(更大,几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
答案 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
优于sed
或awk
的另一个优势;即使大文件主要是二进制数据(它不知道文件的内容),cat
也能正常工作。 sed
和awk
都旨在处理分成行的数据;虽然现代版本可能会很好地处理二进制数据,但它并不是它们的设计目标。
答案 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代码。不过,它对我有用!