I am using Perl for a script that takes in input as two short strings of DNA. As an output, I concatenate the two strings strings then print the second string lined up over its copy at the end of the concatenated string. For example: if input string are AAAA and TTTTT then print:
AAAAATTTTT
TTTTT
I know there are other ways to do this but I am curious to know why my use of tr/// isn't working.
The code for the program is:
use strict;
use warnings;
print "enter a DNA sequence \n";
$DNA1=<>; #<> shorthand for STDIN
$DNA1=~ s/\r?\n?$//;
print $DNA1 "\n\n";
print "enter second DNA sequence \n";
$DNA2=<>;
$DNA2=~ s/\r?\n?$//;
print $DNA2 "\n\n";
$DNA= join("",($DNA1,$DNA2));
print "Both DNA sequences are \"$DNA\" \n\n";
$DNA3=$DNA1;
$DNA3=~ tr/ATCGatcg//;
print $DNA3 "\n\n";
$DNA4= join("",($DNA3,$DNA2));
print $DNA4 "\n\n";
exit;
Your tr changes any of ACTGatcg and removes them. I think you want
$DNA3 =~ tr/atcgATCG/ /;
You need to put a space in the second half of the tr command.
Alternatively, it seems that what you're trying to do is create a variable containing as many spaces as there were characters in the first string:
my $spaces = ' ' x length($DNA1);
It might just be a simple syntax error. Try:
$DNA3 =~ tr/ATCGatcg/ /;
where the second slash separates your two translation entities, and you have a space character between the second and third slashes.
Good luck!
Edit: my mistake - misunderstood what you wanted to do. Answer adjusted accordingly :)
Is this the program that you want?
#!perl
my $s1 = 'AAAAAAAAA';
my $s2 = 'TCGAGCTA';
print
$s1, $s2, "\n",
' ' x length( $s1 ), $s2, "\n";
Related
I have string like this:
$string= "only this I need".
I am new in perl, and I tried to translate a PL/SQL code in perl.
My goal is to replace " with a blank space, finally it should look like this:
$string = only this I need
In PL/SQL I use this, and is working very well:
REGEXP_REPLACE(string,'"','');
In perl I tried this, but is not working: $string=~s/"/''; receiving an error.
Please, help me, tell me what I need to read to do my job properly?
Try this it should work:
use strict;
use warnings;
my $string= '"only this I need"';
print "$string \n"; #prints "only this I need"
$string =~ s/"/ /g;
print "$string \n"; #prints only this I need
This is a way to remove quotes from string:
my $string= '"only this I need"';
$string =~ m/"([^"]*)"/;
print "$1\n";
In case if you know the first and last character is quotes, you can do this without using regex, just use substr:
my $string= '"only this I need"';
$string = substr $string, 1, -1;
print "$string\n";
Question. I am trying to read in perl string from command line e.g. "abcdef" and then split this into "a_b_c_d_e_f".
I am struggling with logic part. any ideas?
#!/usr/bin/perl
while($line=<STDIN>){
chomp $line;
split $line;
join ("_", $line);
print $line;
}
The split manpage actually includes exactly this example:
print join(':', split('', 'abc')), "\n";
Adjusting to use _ instead of : and $line instead of 'abc', we get:
print join('_', split('', $line)), "\n";
The most important point is that split doesn't modify its arguments, it just returns a list, and join doesn't modify its arguments, it just returns a string. So it never makes sense to call split or join without using the return-value.
What you need is
print join('_', split //, $line), "\n";
One-liner:
print join('_', split('', $line)), '\n';
You can read more about perl's split() function here.
Unless you must use split, you can use a between-character substitution for this:
use strict;
use warnings;
my $string = 'abcdef';
$string =~ s/(?<=.)(?:)(?=.)/_/g;
print $string;
Output:
a_b_c_d_e_f
Hope this helps!
I have a Perl question like this:
Write a Perl program that will read a series of last names and phone numbers from the given input. The names and numbers should be separated by a comma. Then print the names and numbers alphabetically according to last name.Use hashes.
Any idea how to solve this?
There's more than one way to do it :)
my %phonebook;
while(<>) {
chomp;
my ($name, $phone) = split /,/;
$phonebook{$name} = $phone;
}
print "$_ => $phonebook{$_}\n" for sort keys %phonebook;
Something like the following perhaps.
my %hash;
foreach(<>){ #reads yor args from commandline or input-file
my #arr = split(/\,/); #split at comma, every line
$hash{$arr[0]} = $arr[1]; #assign to hash
}
#print hash here
foreach my $key (sort keys %hash ) #sort and iterate
{
print "Name: " . $key . " Number: " . $hash{$key} . "\n";
}
Tasks like this are the strength of perl's command line switches. See perldoc perlrun for more infos!
Command line input
$ perl -naF',\s*' -lE'$d{$F[0]}=$F[1];END{say"$_: $d{$_}"for sort keys%d}'
Moe, 12345
Pi, 31416
Homer, 54321
Output
Homer: 54321
Moe: 12345
Pi: 31416
Assuming that we split on commas (you should use Text::CSV generally), we can actually create this hash with a simple application of the map function and the diamond operator (<>).
#!/usr/bin/env perl
use strict;
use warnings;
my %phonebook = map { chomp; split /,/ } <>;
use Data::Dumper;
print Dumper \%phonebook;
The last two lines are just to visualize the result, and the upper three should be in all scripts. The meat of the work is done all in the one line.
I am trying to figure out why the chop function is not working for me when I try to take input from the user:
my $string = <STDIN>;
my $chr = chop($string);
print "String: $string\n";
print "Char: $chr\n";
output
perl chop.pl
hello
String: hello
Char:
But if I use a string, then it works!
my $string = "frong";
my $chr = chop($string);
print "String: $string\n";
print "Char: $chr\n";
output
[583]
perl chop.pl
String: fron
Char: g
When you pass input from console, chop is chopping the newline that is at the end of the string, which is present when you hit Enter. While your string does not contain that.
What you're chop()'ing is the newline at the end of the string. To remove the newline upon assignment from STDIN:
chomp(my $string = <STDIN>);
In other words, your program should look like this:
chomp(my $string = <STDIN>);
my $chr = chop($string);
print "String: $string\n";
print "Char: $chr\n";
Checking the perl documentation for these two functions chop and chomp might just do.
chomp
chomp This safer version of "chop" removes any trailing string that
corresponds to the current value of $/ (also known as
$INPUT_RECORD_SEPARATOR in the "English" module.
chop
chop Chops off the last character of a string and returns the
character chopped.
Hope this help
If you're printing diagnostics to show variable contents, put some form of delimiter around them, then you'd see the newline in your $chr example.
eg.
print "String: \"$string\"\n";
print "Char: \"$chr\"\n";
I recorded some data on my laptop and because the OS system language is German it converted the decimal separator to a comma (didn't think of that at the time...).
The column separator (there are three columns in the text file) is a comma too and so I end up with six columns instead of three
Example.txt
4,0,5,0,6,0
should be
4.0, 5.0, 6.0
How can I loop through all files in a folder and replace every first, third and fifth comma with a point in all lines in my data-files? I would prefer a bash script (.sh) or possibly a perl solution
Or how about awk
for F in * ; do awk -F, 'BEGIN { OFS = "," } ; { print $1"."$2, $3"."$4, $5"."$6 } ' $F | sponge $F ; done
You need "moreutils" for sponge, by the way. And back up your files first!
Generally for csv parsing you should use Text::CSV, however for this correction task, a quick and dirty could be:
#!/usr/bin/perl
use strict;
use warnings;
my $output;
#onen my $out, '>', 'outfile.dat';
#open my $in, '<', 'infile.dat';
#while(<$in>){
while(<DATA>){
chomp;
my #fields = split ',';
while (#fields) {
$output .= shift(#fields) . '.' . shift(#fields);
$output .= ', ' if #fields;
}
$output .= "\n";
}
#print $out $output;
print $output;
__DATA__
4,0,5,0,6,0
4,0,5,0,6,0
of course you will read from a file rather than DATA and print to a new file presumably. I have added this real-world usage as comments.
Well I see lots of valid and good answers here, here's another.
perl -wpe 'my $i; s/,/($i^=1) ? "." : ","/ge'
Here /e means "execute the replacement part"; $i^=1 generates a 1,0,1,0...sequence, and x?y:z selects y or z based on x's value (i.e. if (x) {y} else {z})
Following perl script should help you.
perl -e '$a = $ARGV[0]; $a =~ s/(\d)\,(\d\,)?/$1\.$2/g; print $a' "4,0,5,0,6,0"
OUTPUT
4.0,5.0,6.0
In Perl, the necessary regex would be s/,([^,]*,?)/.$1/g. If you apply this to a string, it will replace the first comma with a period, preserve the next comma (if any), and then start looking for commas again after the second one.