Combining loop with awk

Viewed 57

I need help combining an awk with a loop.

I have two files, one Bedfile.bed and a Samplelist.txt that look like this:

Bedfile.bed

HiC_scaffold_2  1       50001

HiC_scaffold_2  400001  450001

HiC_scaffold_2  800001  850001

Samplelist.txt

sampleA
sampleB
sampleC

I would like to create a new Bedfile for each sample (from the Samplelist.txt) in which I include the sample name as a new column next to each line, and I add the name in the output. Looking like this, e.g., for the first two sample

Bedfile_SampleA.bed

HiC_scaffold_2  1       50001 SampleA

HiC_scaffold_2  400001  450001 SampleA

HiC_scaffold_2  800001  850001 SampleA

Bedfile_SampleB.bed

HiC_scaffold_2  1       50001 SampleB

HiC_scaffold_2  400001  450001 SampleB

HiC_scaffold_2  800001  850001 SampleB

I have done this for one file but I have more than a hundred files, so I would like to do some sort of loop using a sample list.

awk ' {print $1"\t"$2"\t"$3"\t""SampleA"}' Bedfile.bed >  Bedfile_SampleA.bed

Any suggestion?

3 Answers
$ awk -v OFS='\t' '
    NR==FNR { samples[$0]; next }
    FNR == 1 {
        base = FILENAME
        sub(/\..*/,"",base)
    }
    {
        for ( sample in samples ) {
            out = base "_" sample ".bed"
            print $0 (NF ? OFS sample : "") > out
        }
    }
' Samplelist.txt Bedfile.bed

$ head Bedfile_*
==> Bedfile_sampleA.bed <==
HiC_scaffold_2  1       50001   sampleA

HiC_scaffold_2  400001  450001  sampleA

HiC_scaffold_2  800001  850001  sampleA

==> Bedfile_sampleB.bed <==
HiC_scaffold_2  1       50001   sampleB

HiC_scaffold_2  400001  450001  sampleB

HiC_scaffold_2  800001  850001  sampleB

==> Bedfile_sampleC.bed <==
HiC_scaffold_2  1       50001   sampleC

HiC_scaffold_2  400001  450001  sampleC

HiC_scaffold_2  800001  850001  sampleC

The above will work in any awk, assuming you don't have too many output files to exceed the "too many open files" limit. If you do, it'll still work with GNU awk, and there's a simple tweak to make it work with any awk.

Thus is very straightforward in awk. First you read the sample file in memory, and then you process the full bed-file

awk 'BEGIN{OFS="\t"}(FNR==NR){a[$0]; next}{for(i in a){f=FILENAME"."i; print $0,i > f}}' sample.txt bed.txt

You can do the operation and the loop all in AWK, but if you wanted to do the loop 'separately' for another reason, you could use:

while read -r sample
do
     awk -v var="$sample" 'BEGIN{OFS="\t"} {print $0, var}' bedfile.bed > bedfile_"$sample".bed
done < samplelist.txt
Related