Not able to split a string in perl - getting unmatched ( in regex; marked by (-- Here in m/ error - perl

The below is my code
$var = ' "jjjjjjjj&Q_30006_47=540IT%20(540%2FOR%2FHPSC%2FD%2F02%2F11&Q_30006_4=&Q_30006_6=12&Q_30006_7=&Q_30006_" &';
($temp1,$temp2) = split($var,"&");
print $temp1;
I need to get
$temp1 = "jjjjjjjj
and
$temp2 as the remaining part of the string after the first &.
I am getting error because of the '(' in the string.
Can anyone please advise on how to split this.
Thanks!!

I think that you have the parameter orders wrong. The pattern should be first:
($temp1,$temp2) = split("&", $var);
However, that will split on all & characters. You probably are looking for this (the 2 is the limit):
($temp1,$temp2) = split("&", $var, 2);

($temp1,$temp2) = split '&', $var, 2;

Related

removing trailing words end with : from a string using perl

i have question on how to remove specific set of words that end with : in a string using perl.
For instance,
lunch_at_home: start at 1pm.
I want to get only "start at 1 pm"after discarding "lunch_at_home:"
note that lunch_at_home is just an example. It can be any string with any length but it should end with ":"
This should do the job.
my $string = "lunch_at_home: start at 1pm."
$string =~ s/^.*:\s*//;
It will remove all char before : including the :
If you want to remove a specific set of words that are set apart from the data you want:
my $string = 'lunch_at_home: start at 1pm.';
$string =~ s/\b(lunch_at_home|breakfast_at_work):\s*//;
That would leave you with start at 1pm. and you can expand the list as needed.
If you just want to remove any "words" (we'll use the term loosely) that end with a colon:
my $string = 'lunch_at_home: start at 1pm.';
$string =~ s/\b\S+:\s*//;
You'd end up with the same thing in this case.
take
my $string = "lunch_at_home: start at 1pm.";
to remove everything up to the last ":" and the period at the end of the entry as in your question:
$string =~ s/.*: (.*)\./$1/;
to remove everything up to the first ":"
$string =~ s/.*?: (.*)\./$1/;
split on : and discard the first part:
my (undef, $value) = split /:\s*/, $string, 2;
The final argument (2), ensures this works correctly if the trailing string contains a :.
You can use split function to achieve this:
my $string = "lunch_at_home: start at 1pm.";
$string = (split /:\s*/, $string)[1];
print "$string\n";

Read string within double quotes in perl

I have a file which contains lines like this:
"pin1" Inpin; "pin2" outpin; "pin3" inoutPin;
some other string "pin4" inpin
I want to store just pin1, pin2, pin3, pin4 (basically words within double quotes). Can someone please help..? Basically read one line at a time and grab the word within double quotes only. I tried to split a line by ";" but it doesn't work since ";" may not be present in all lines.
thanks!
join ', ' $str =~ /"([^"]*)"/g
try this code:
my $string = '"pin1" Inpin; "pin2" outpin; "pin3" inoutPin;`';
my #array;
while ( $string =~ /\"(.+?)\"/ )
{
put (array, $1.),
$string =~ s/\"$1\"//;
}

MySQL Query with variable in Perl

My Perl is fairly rusty so please forgive. Trying to write a query using a variable. Have tried reformatting, just can't seem to get it correctly. Here is my code, not sure what I'm doing wrong.
my $d_var = "$3\n";
my $query="SELECT id FROM `accounts` WHERE (`accounts`.`named` = ?) LIMIT 1";
my $st_h = $db_h->prepare($query);
$st_h->bind_param(1, '$d_var');
$st_h->execute;
my $row = $st_h->fetchrow_array();
Please double check:
$3 contains something reasonable
concatenating $3's value and "\n" (by interpolation) is correct ("\n" in field?)
as ' doesn't interpolate => my $st_ht->bind_param(1, $d_var);
(I don't understand the DBI Docs as Chris Ledet does.)
On 2nd thought:
This code snippet:
my $v = "nix nix 1001";
print "$v\n";
print '$v\n', "\n";
if ($v =~ m/(nix) (nix) (\d+)/) {
print 'found: ', $3, "\n";
$sth = $dbh->prepare('SELECT * FROM sample01.csv WHERE GRUPPE=?');
$sth->bind_param(1, $3);
$sth->execute;
while(my #row = $sth->fetchrow_array()) {
print '|', join( '|', #row ), "|\n";
}
} else {
print "no match\n";
}
and the output:
DBI: 1.616 DBD::CSV: 0.33
|00000089-6d83-486d-9ddf-30bbbf722583|2011-09-17 16:25:09|1001|
|000004c9-92c6-4764-b320-b1403276321e|2011-11-09 13:52:30|2000|
nix nix 1001
$v\n
found: 1001
|00000089-6d83-486d-9ddf-30bbbf722583|2011-09-17 16:25:09|1001|
should illustrate:
' does not interpolate, your '$d_var' will pass this variable name literally to DBI
a valid match needs no "\n" to 'work'
the param sequence for bind_param is number, value
Not sure why you're even using bind_param. In my opinion, it's far simpler to just pass extra values into execute.
my $d_var = "$3\n";
my $query = 'SELECT id FROM accounts` WHERE (`accounts`.`named` = ?) LIMIT 1';
my $st_h = $db_h->prepare($query);
$st_h->execute($d_var);
my $row = $st_h->fetchrow_array();
Have you considered switching to DBIx::Class?
What does this mean?
my $st_ht->bind_param(1, '$d_var');
There is no variable being introduced, so why the my?
I have $3 printing out prior to execution and there is data contained within the string.
I have d_var="$3\n" as the variable $3 is being generated by a Regex string and doesn't seem to work without \n.
Tried what Chris suggested above, however did not work.
Aside from what Dan said (removing the single quote), you binded your param to a possibly none Statement handle object $st_ht->bind_param(...) it should be $st_h->bind_param(...).

How can I expand a string like "1..15,16" into a list of numbers?

I have a Perl application that takes from command line an input as:
application --fields 1-6,8
I am required to display the fields as requested by the user on command line.
I thought of substituting '-' with '..' so that I can store them in array e.g.
$str = "1..15,16" ;
#arr2 = ( $str ) ;
#arr = ( 1..15,16 ) ;
print "#arr\n" ;
print "#arr2\n" ;
The problem here is that #arr works fine ( as it should ) but in #arr2 the entire string is not expanded as array elements.
I have tried using escape sequences but no luck.
Can it be done this way?
If this is user input, don't use string eval on it if you have any security concerns at all.
Try using Number::Range instead:
use Number::Range;
$str = "1..15,16" ;
#arr2 = Number::Range->new( $str )->range;
print for #arr2;
To avoid dying on an invalid range, do:
eval { #arr2 = Number::Range->new( $str )->range; 1 } or your_error_handling
There's also Set::IntSpan, which uses - instead of ..:
use Set::IntSpan;
$str = "1-15,16";
#arr2 = Set::IntSpan->new( $str )->elements;
but it requires the ranges to be in order and non-overlapping (it was written for use on .newsrc files, if anyone remembers what those are). It also allows infinite ranges (where the string starts -number or ends number-), which the elements method will croak on.
You're thinking of #arr2 = eval($str);
Since you're taking input and evaluating that, you need to be careful.
You should probably #arr2 = eval($str) if ($str =~ m/^[0-9.,]+$/)
P.S. I didn't know about the Number::Range package, but it's awesome. Number::Range ftw.
I had the same problem in dealing with the output of Bit::Vector::to_Enum. I solved it by doing:
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
then also in my file:
sub expand_range
{
return join(",",($_[0] .. $_[1]));
}
So "1,3,5-7,9,12-15" turns into "1,3,5,6,7,9,12,13,14,15".
I tried really hard to put that expansion in the 2nd part of the s/// so I wouldn't need that extra function, but I couldn't get it to work. I like this because while Number::Range would work, this way I don't have to pull in another module for something that should be trivial.
#arr2 = ( eval $str ) ;
Works, though of course you have to be very careful with eval().
You could use eval:
$str = "1..15,16" ;
#arr2 = ( eval $str ) ;
#arr = ( 1..15,16 ) ;
print "#arr\n" ;
print "#arr2\n" ;
Although if this is user input, you'll probably want to do some validation on the input string first, to make sure they haven't input anything dodgy.
Use split:
#parts = split(/\,/, $fields);
print $parts[0];
1-6
print $parts[1];
8
You can't just put a string containing ',' in an array, and expect it to turn to elements (except if you use some Perl black magic, but we won't go into that here)
But Regex and split are your friends.

How can I use the "s///" operator in order to change number of values?

I have a file that contains:
foo1 = 1
foo2 = 2
foo3 = 8
.
.
.
I need to replace only the values (1,2,8...) in that file with part of a memory hash values, the ones with the same keys (foo1 -> 33,foo2 -> 44,foo3...) How can I change it using the "s///" operator? If there is other elegant ways to conduct it I'll be happy to know.
Thanks for any help,
Yohad.
my %new_values = ( foo1 => 33, ... );
$data =~ s{^(?<key>\w+) = \K(?<old_value>.+)$}
{$new_values{$+{key}}}gem;
The key is the "e" flag which lets you run code to determine the replacement. The (?<...>) syntax increases readability, and the \K allows us to match the entire line but only replace the value area. The "g" flag repeats the substitution as many times as possible, and the "m" flag makes ^...$ match a line instead of the entire string. (The g and m will probably be unnecessary if you split the lines before application of the regexp.)
Here's one
%h = ("foo1"=>3, "foo2"=>5);
while (<>)
{
#Substitute value according to expression on right hand side
s/(\w+) = .*/$1 . " = ". $h{$1}/e;
print;
}
one way
%hash = ("foo1"=>33,"foo2" => 44,"foo3"=>99);
while (<>){
chomp;
( $one , $two ) = split /\s+=\s+/, $_;
print "$one = $hash{$one} \n"
}
s/regexPattern/replacementPattern/flags
"I am a string!"
s/\sam/'s/g
"I's a string!"
http://gnosis.cx/publish/programming/regular_expressions.html
I really can't understand what you're doing based on the descriptoin. Can you provide sample input and output?