The following code works well for me, but I am not able to figure out how to separate columns with a field-separator like comma (,) character.
Please advise, thanks.
#! /usr/bin/perl
use strict;
use warnings;
use Spreadsheet::ParseExcel::Simple;
my #data;
my $xls = Spreadsheet::ParseExcel::Simple->read('mylargefile.xls');
foreach my $sheet ($xls->sheets) {
while ($sheet->has_data) {
#data = $sheet->next_row;
print "#data \n";
}
}
Since #data is an array of cells, you can use the built-in join() function like so:
print join(',', #data);
Or replace the comma with a separator of your choice.
Related
First of I have to apologize for editing my initial post. But after I provide my code I did the question fuzzy.
So, I have this an array (#start_cod) containing lines separated by /n as follows:
print #start_cod;
tatatattataattatatttat
cacacacaacaccacaac
aaaaaaaaaaaaaaa
I need to remove the newlines and add ">text" ONLY at the beginning of the array as follow:
>text
tatatattataattatatttatcacacacaacaccacaacaaaaaaaaaaaaaaa
I tried:
s/\s+\z// for #start_cod;
print ">text#start_cod";
I tried also with chomp
chomp #start_cod;
print ">text#start_cod";
and
my #start_cod = split("\n",$start_cod);
$start_cod = join("",#start_cod);
print ">text$start_cod";
but I get
aaaaaaaaaaaaaaaaaaa>textcacacacacaacaccacaac>textaattatatattataattatatttat
Any suggestions on how to handle this in Perl Programming?
Here is my code which works 100%.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my %alliloux =();
$/="\n>";
while (<>) {
s/>//g;
my ($onoma, #seq) = split (/\n/, $_);
my ($sp, $head) = split (/\./, $onoma);
push #{ $alliloux{$sp} }, join "\n", ">$onoma", #seq;
}
foreach my $sp (keys %alliloux) {
chomp $sp;
my ($head, $dna) = split(/\t/, $sp);
my #start_cod = substr($dna, 3);
say #start_cod;
Input file:
>name aaaaaaaaaaaaaaaaaa
>name2 acacacacacaacaccacaac
>namex aattatatattataattatatttat
output after Perl run
tatatattataattatatttat
cacacacaacaccacaac
aaaaaaaaaaaaaaa
Desired output:
>text
tatatattataattatatttatcacacacaacaccacaacaaaaaaaaaaaaaaa
If I understand your question correctly, this should do what you want:
use strict;
use warnings;
my #start_cod = (
'aaaaaaaaaaaaaaaaaa',
'acacacacacaacaccacaac',
'aattatatattataattatatttat',
);
print ">text\n", #start_cod, "\n";
The print first prints ">text" and a newline once, then you get the #start_cod items on a line, and the last "\n" makes sure you have a newline after the last element.
Output:
>text
aaaaaaaaaaaaaaaaaaacacacacacaacaccacaacaattatatattataattatatttat
You might want to see Read FASTA into Hash. It's the same problem and very close to the code I wrote before I read it. Also, there are modules on CPAN that can handle FASTA.
I think you want to combine the sequences that start with the same name, disregarding the numbers. The sequences shouldn't have interior whitespace. In your code, you are constantly adding whitespace. You even join on a newline. So, you go to the doctor and say "My arm hurts when I do this", and the doctor says "So don't do that". :)
When you run into these sort of problems, check the results of your operations at each step to see if you get what you expect. Here's a much simplified version of a program that I think does what you want. I've removed most of the data structure because they are complicating your process.
In short, read a line and remove the newline at the end. That's one source of your newlines. Then, extract the sequence and concatenate that to the previous sequence. When you join with newlines, you are adding newlines. So, don't do that:
use v5.14;
use warnings;
use Data::Dumper;
my %alliloux = ();
while (<DATA>) {
chomp; # get rid of that newline!
s/>//g;
# now split on whitespace, but only up to two parts.
# There's no array here.
my( $name, $seq ) = split /\s+/, $_, 2;
# remove the numbers at the end to get the prefix of the
# name.
my $prefix = $name =~ s/\d+\z//r;
# append the current sequence for this prefix to what we
# have already seen.f
$alliloux{$prefix} .= $seq;
}
say Dumper( \%alliloux );
foreach my $base ( keys %alliloux ) {
say ">text $alliloux{$base}";
}
__DATA__
>name aaa
>name2 cccc
>name99 aattaatt
You don't need the intermediate array. You can build up your string as you go. You don't need to have all the parts before you do that.
Now, to figure out where you might be going wrong, do a little at once. Ensure that you've extracted the right thing. It's handle to put characters around the variables you interpolate so you can see whitespace at the beginning or end:
while (<DATA>) {
chomp; # get rid of that newline!
s/>//g;
my( $name, $seq ) = split /\s+/, $_, 2;
say "Name: <$name>";
say "Seq: <$seq>"
}
Then, add another step, and ensure that works:
while (<DATA>) {
chomp; # get rid of that newline!
s/>//g;
my( $name, $seq ) = split /\s+/, $_, 2;
say "Name: <$name>";
say "Seq: <$seq>"
my $prefix = $name =~ s/\d+\z//r;
say "Prefix: <$prefix>";
}
Repeat this process for each step. Then, when you come with a question, you've pinpointed the point where things diverge. Here's the same technique in your program:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
while (<DATA>) {
s/>//g;
my ($onoma, #seq) = split (/\n/, $_);
say "Onoma: <$onoma>";
}
__DATA__
>name aaa
>name2 cccc
>name99 aattaatt
The output shows that you never had anything in #seq. You are splitting on a newline, but unless you've changed the default line ending, you'll only get a newline at the end:
Onoma: <name aaa>
Onoma: <name2 cccc>
Onoma: <name99 aattaatt>
Now there's nothing in #seq, so a line like join "\n", ">$onoma", #seq; is really just join "\n", ">$onoma". You could have seen that with a little checking.
The description lacks clarity of the problem.
By looking at the desired output the following code comes to mind. Please see if it does what you was looking for.
Even looking at your code it is not clear what you try to do -- some part of the code does not make much sense.
use strict;
use warnings;
use feature 'say';
my #start_cod;
while( <DATA> ) {
chomp;
next unless />\s?name.?\s+(.*)/;
push #start_cod, $1;
}
print ">text\n " . join('',#start_cod);
__DATA__
>name aaaaaaaaaaaaaaaaaa
>name2 acacacacacaacaccacaac
.
.
.
> namex aattatatattataattatatttat
If one string is expressed like below
$str = "5+2-1";
I'd like to get the calculation result from that string.
How do I convert to scalar to compute this?
Thanks.
The easiest way to do this:
print eval('5+2-1');
but it's not safe:
print eval('print "You are hacked"');
You need to check string before eval it.
Also you can use Math::Expression module or many other modules from cpan:
#!/usr/bin/perl
use strict;
use warnings;
use Math::Expression;
my $env = Math::Expression->new;
my $res = $env->Parse( '5+2-1' );
# my $res = $env->Parse( 'print you are hacked' ); # no math expression here
print $env->Eval( $res );
If you are sure the string does not contain any malicious code you can use eval to treat the content of it as perl code.
#!/usr/bin/perl
use strict;
use warnings;
my $string = "5+2-1";
print eval($string);
#print 6
Here's I want to archive. I want to split a one-liner comma-separated and insert #domain.com then join it back as comma-separated.
The one-liner contains something like:
username1,username2,username3
and I want to be something like:
username1#domain.com,username2#domain.com,username3#domain.com
So my Perl script that I tried which doesn't not work properly:
my $var ='username1,username2,username3';
my #tkens = split /,/, $var;
my #user;
foreach my $tken (#tkens) {
push (#user, "$tken\#domain.com");
}
my $to = join(',',#user);
Is there any shortcut on this in Perl and please post sample please. Thanks
Split, transform, stitch:
my $var ='username1,username2,username3';
print join ",", map { "$_\#domain.com" } split(",", $var);
# ==> username1#domain.com,username2#domain.com,username3#domain.com
You could also use a regular expression substitution:
#!/usr/bin/perl
use strict;
use warnings;
my $var = "username1,username2,username3";
# Replace every comma (and the end of the string) with a comma and #domain.com
$var =~ s/$|,/\#domain.com,/g;
# Remove extra comma after last item
chop $var;
print "$var\n";
You already have good answers. Here I am just telling why your script is not working. I didn't see any print or say line in your code, so not sure how you are trying to print something. No need of last line in your program. You can simply suffix #domain.com with each value, push to an array and print it with join.
#!/usr/bin/perl
use strict;
use warnings;
my $var = 'username1,username2,username3';
my #tkens = split ',', $var;
my #user;
foreach my $tken (#tkens)
{
push #user, $tken."\#domain.com"; # `.` after `$tken` for concatenation
}
print join(',', #user), "\n"
Output:
username1#domain.com,username2#domain.com,username3#domain.com
I have a multiline string as input. For example: my $input="a\nb\nc\nd"
I would like to create a set from this input, so that I can determine whether elements from a vector of strings are present in the set. My question is, how do I create a set from a multi-line string in Perl?
split can be used to store lines into an array variable:
use warnings;
use strict;
use Data::Dumper;
my $input = "a\nb\nc\nd";
my #lines = split /\n/, $input;
print Dumper(\#lines);
__END__
$VAR1 = [
'a',
'b',
'c',
'd'
];
#toolic is right; split does the trick to grab the input.
But you might want to go a step further and put those values into a hash, if you want to check set membership later on. Something like this:
use warnings;
use strict;
my $input = "a\nb\nc\nd";
my #lines = split /\n/, $input;
my %set_contains;
# set a flag for each line in the set
for my $line (#lines) {
$set_contains{ $line } = 1;
}
Then you can quickly check set membership like this:
if ( $set_contains{ $my_value } ) {
do_something( $my_value );
}
I'm trying to find the index of the first occurrence of a number from 0-9.
Let's say that:
$myString = "ABDFSASF9fjdkasljfdkl1"
I want to find the position where 9 is.
I've tried this:
print index($myString,[0-9]);
And:
print index($myString,\d);
Use regex Positional Information:
use strict;
use warnings;
my $myString = "ABDFSASF9fjdkasljfdkl1";
if ($myString =~ /\d/) {
print $-[0];
}
Outputs:
8
You can try even below perl code:
use strict;
use warnings;
my $String = "ABDFSASF9fjdkasljfdkl11";
if($String =~ /(\d)/)
{
print "Prematch string of first number $1 is $`\n";
print "Index of first number $1 is " . length($`);
}
You can try this:
perl -e '$string="ABDFSASF9fjdkasljfdkl1";#array=split(//,$string);for $i (0..$#array) {if($array[$i]=~/\d/){print $i;last;}}'