Bioinfocoder has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to read in a template config (template.config) file like ( which is little more complex then then the one posted earlier -

[module1] ;;path to speedseq package binary directory $;SPEEDSEQ_BIN_DIR$; = /usr/local/packages/ ;;Sequence file 1 $;Seq1File$; = ;;Sequence file 2 $;Seq2File$; = ;;Read Group $;Read_Group$;='@RG\tID:NA12878\tSM:NA12878\tPL:ILLUMINA\tLB:NA12878\t +PU:NA12878' ;;Reference $;Reference$; = [module2] ;;Output Chromosome $;Chromosome$; = ;;use --v for verbose summary $;OTHER_ARGS$; = --v
whose fields will get populated by user input on command line eg

 perl script.pl template.config --seq1 USER_INPUT.txt --Seq2 USER_INPT2.txt --Ref USER_INPUT_REF.txt --chr_list USER_INPUT_CHR.txt

and it will output a populated a new config file like -

[module1] ;;path to speedseq package binary directory $;SPEEDSEQ_BIN_DIR$; = /usr/local/packages/ ;;Sequence file 1 $;Seq1File$; = "USER_INPUT.txt" ;;Sequence file 2 $;Seq2File$; = "USER_INPT2.txt" ;;Read Group $;Read_Group$;='@RG\tID:NA12878\tSM:NA12878\tPL:ILLUMINA\tLB:NA12878\t +PU:NA12878' ;;Reference $;Reference$; = "USER_INPUT_REF.txt" [module2] ;;Output Chromosome $;Chromosome$; = "USER_INPUT_CHR.txt" ;;use --v for verbose summary $;OTHER_ARGS$; = --v

I tried with hash also, but that is not keeping the output order same as in the input file. I would really appreciate if anyone can provide suggestions on how to approach this.

Here is my Code -

my ($template_name, $Prefix, $Seq1File,$Seq2File,$Align_Reference,$Chr +omosome_list,$Reference,$KnownSites ) = @ARGV; GetOptions ('template_config=s' => \$template_name, 'Project=s' => \$P +refix, 'Fasta_seq1=s' => \$Seq1File, 'Fasta_seq2=s' => \$Seq2File, 'R +ef_align=s' => \$Align_Reference, 'Chr_list=s' => \$Chromosome_list, +'Ref=s' => \$Reference, 'Sites=s' => \$KnownSites); open my $in_fh, '<', $template_name; my %field = map { s/^\s+|\s*\n$//g; $_; } grep { !/^\s*#|^\s*$/ } <$i +n_fh>; close $in_fh; foreach my $spec (sort keys %field) { if($spec =~ m/Output\s+Prefix/) { $field{$spec} = $field{$spec} .= $Prefix; } elsif ($spec =~ m/Sequence\s+file\s+1/) { $field{$spec} = $field{$spec} .= $Seq1File; } elsif ($spec =~ m/Sequence\s+file\s+2/) { $field{$spec} = $field{$spec} .= $Seq2File; } elsif ($spec =~ m/Align_Reference/) { $field{$spec} = $field{$spec} .= $Align_Reference; } elsif ($spec =~ m/Chromsome\s+List\s+file/) { $field{$spec} = $field{$spec} .= $Chromosome_list; } elsif ($spec =~ m/Reference/) { $field{$spec} = $field{$spec} .= $Reference; } elsif ($spec =~ m/Known\s+sites/) { $field{$spec} = $field{$spec} .= $KnownSites; } } # Print it to an output file { #open my $output_file = './test_processing.txt'; open my $out_fh, '>', './complete_nicu.txt'; foreach my $key (keys %field) { print $out_fh "$key\n"; print $out_fh "$field{$key}\n"; print "$field{$key}\n"; } close $out_fh; }
Thanks!

Replies are listed 'Best First'.
Re: Read in a template file, populate using user input and and generate a new file
by toolic (Bishop) on Feb 25, 2016 at 21:08 UTC

      I can only hope that some day I will also have attained enlightenment to the state where I am able answer an untitled node with no question asked!

        My bad! the post dint get through!
Re: Read in a template file, populate using user input and and generate a new file
by hippo (Archbishop) on Feb 26, 2016 at 09:26 UTC

    If I've reverse engineered a spec from your post correctly, then something along these lines should suffice:

    #!/usr/bin/env perl use strict; use warnings; use feature 'say'; my $infile = shift; open my $in, '<', $infile or die "Cannot open $infile: $!"; while (<$in>) { chomp; s/=\s*$/"= " . shift/e; say; } close $in;

    Running it with your sample input gives:

    $ ./bar.pl template.config list.txt file_list.txt ;; path to config file $;INPUT_FILE$; = list.txt ;; path to list of config files $;INPUT_FILE_LIST$; = file_list.txt ;; path to temporary directory $;TEMP_DIR$; = $;TMP_DIR$; ;; use --v for verbose summary $;OTHER_ARGS$; = --v

    Update: removed a redundant mention of @ARGV in the substitution.

    Update 2: for the avoidance of any confusion resulting from the parent post having been rewritten to change both the data set and the invocation, here's the original input file:

    ;; path to config file $;INPUT_FILE$; = ;; path to list of config files $;INPUT_FILE_LIST$; = ;; path to temporary directory $;TEMP_DIR$; = $;TMP_DIR$; ;; use --v for verbose summary $;OTHER_ARGS$; = --v

    which was declared to be called as I have above and result in the output which I have also shown above.

      Thanks! but I just came to know that the input is little different then teh earlier post, I will try your suggestion as well!

        If you can add placeholders [% name %] to your template.config file like this

        [module1] ;;path to speedseq package binary directory $;SPEEDSEQ_BIN_DIR$; = /usr/local/packages/ ;;Sequence file 1 $;Seq1File$; = "[% seq1 %]" ;;Sequence file 2 $;Seq2File$; = "[% seq2 %]" ;;Read Group $;Read_Group$;='@RG\tID:NA12878\tSM:NA12878\tPL:ILLUMINA\tLB:NA12878\t +PU:NA12878' ;;Reference $;Reference$; = "[% ref %]" [module2] ;;Output Chromosome $;Chromosome$; = "[% chr_list %]" ;;use --v for verbose summary $;OTHER_ARGS$; = --v

        then you could use a templating module like Template::Toolkit or Template::Tiny

        poj
Re: Read in a template file, populate using user input and and generate a new file
by CountZero (Bishop) on Feb 26, 2016 at 07:35 UTC
    What's in "script.pl"? Did it come with any documentation?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
      its just the script with code in it, that user will use to run the job on command line