Replace text to number php - replace

I need to replace a simple text with comma inside to number.
CSV File:
Test1
Test1, Test2
Test1, Test2, Test3
php code
$text = "Test1";
$text1 = "Test1, Test2";
$text1 = "Test1, Test2, Test3";
$search = array('$text','$text1','$text2');
$replace = array('10','11','12');
$result = str_replace($search, $replace, $file);
echo "$result";
the result is: "10","10, 11","10, 11, 12"
but I want to get "10","11","12".
This is the final script but on one of this im getting "10, 12"
$text1 = "Test1";
$text2 = "Test2";
$text3 = "Test3";
$text4 = "Test1, Test2, Test3";
$text5 = "Test1, Test2";
$text6 = "Test1, Test3";
$text7 = "Test2, Test3";
$text8 = "Blank";
array($text8,$text7,$text6,$text5,$text4,$text3,$text2,$text1);
array('10','11','12','13','14','15','16','17');

You probably don't want to have these string literals:
$search = array('$text','$text1','$text2');
Try
$search = array($text,$text1,$text2);
When you use single-quotes, variables are not parsed, so
$text1 = 'Hello';
$text2 = '$text1';
echo $text2; // $text1
Vs
$text1 = 'Hello';
$text2 = $text1;
echo $text2; // Hello
The result from:
Test1
Test1, Test2
Test1, Test2, Test3
Would be that each instance of Test1 is replaced with 10, and so on - so:
10
10, 11
10, 11, 12
Update
I see what you are trying to do. When you pass arrays into str_replace it processes them in order - so by the time it looks for Test1, Test2 you have already replaced Test1 with 10. Reverse the order to do what you want...
$text = "Test1";
$text1 = "Test1, Test2";
$text2 = "Test1, Test2, Test3";
$search = array($text2,$text1,$text); // reversed
$replace = array('12', '11', '10');// reversed
$result = str_replace($search, $replace, $file);
echo $result;

Related

Substitute only in the matched part of a Perl pattern

How can I substitute only in matched pattern and put it back in same variable using Perl?
For example:
my $str = "a.b.AA pat1 BB hgf AA pat1 BB jkl CC pat1 don't change pat1";
I want to match pat1 between AA and BB and replace it with Original string PAT2. However, I don't want to replace pat1 anywhere else in the same string
Expected output string:
a.b.AA PAT2 BB hgf AA PAT2 BB jkl CC pat1 don't change pat1
I am sure there should be some good way to do it; please advise.
Original string:
my $ORG_str = 'A.B.C.\\valid.A .\\valid.A.B.C .\\valid.X.Y.Z .p.q.r.s';
Expected String:
my $EXP_op = 'A.B.C.\\valid?A .\\valid?A?B?C .\\valid?X?Y?Z .p.q.r.s';
Substitute character . to ? only if it is between backslash \ and whitespace .
Look into look-around regexes.
s/(?<=AA )pat1(?= BB)/pat2/g
This matches and replaces a pat1 surrounded by AA and BB.
Not very simple with one single regexp, so I used divide and conquer to compute the result. This is a small recursive function that is replacing a single '.' per group of ('\' ' ')
The iteration ends when there is nothing to replace
sub replace {
my ($input) = #_;
my $result = $input;
$result =~ s/(\\\S*?)\.(.*? )/$1?$2/g;
return $result if $result eq $input;
return replace($result);
}
The function with some test cases
use strict;
my $ORG_str= 'A.B.C.\\\\valid.A .\\\\valid.A.B.C .\\\\valid.X.Y.Z .p.q.r.s';
my $EXP_op ='A.B.C.\\\\valid?A .\\\\valid?A?B?C .\\\\valid?X?Y?Z .p.q.r.s';
sub replace {
my ($input) = #_;
my $result = $input;
$result =~ s/(\\\S*?)\.(.*? )/$1?$2/g;
return $result if $result eq $input;
return replace($result);
}
my $check;
my $result;
my $expected;
$check = 'abcd'; $expected = $check;
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
$check = 'ab\xxx. cd'; $expected = 'ab\xxx? cd';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
$check = 'ab\x.x.x. cd'; $expected = 'ab\x?x?x? cd';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
$check = 'ab\x.x.x. cd\y.y.y.'; $expected = 'ab\x?x?x? cd\y.y.y.';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
$check = 'ab\x.x.x. cd\xxx.xxx..xxx...x \y.y.y.'; $expected = 'ab\x?x?x? cd\xxx?xxx??xxx???x \y.y.y.';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
$check = '. ..\.. ...\.. ...\.. ...\..'; $expected = '. ..\?? ...\?? ...\?? ...\..';
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
$check = $ORG_str; $expected = $EXP_op;
$result = replace($check);
assert($result eq $expected, "'$check' gives '$expected'");
sub assert {
my ($cond, $mesg) = #_;
print "checking $mesg ... ";
die "\nFAIL: $mesg" unless $cond;
print "OK\n";
}
The result
checking 'abcd' gives 'abcd' ... OK
checking 'ab\xxx. cd' gives 'ab\xxx? cd' ... OK
checking 'ab\x.x.x. cd' gives 'ab\x?x?x? cd' ... OK
checking 'ab\x.x.x. cd\y.y.y.' gives 'ab\x?x?x? cd\y.y.y.' ... OK
checking 'ab\x.x.x. cd\xxx.xxx..xxx...x \y.y.y.' gives 'ab\x?x?x? cd\xxx?xxx??xxx???x \y.y.y.' ... OK
checking '. ..\.. ...\.. ...\.. ...\..' gives '. ..\?? ...\?? ...\?? ...\..' ... OK
checking 'A.B.C.\\valid.A .\\valid.A.B.C .\\valid.X.Y.Z .p.q.r.s' gives 'A.B.C.\\valid?A .\\valid?A?B?C .\\valid?X?Y?Z .p.q.r.s' ... OK
\\\\[^. ]*\K|(?!^)\G\.([^. ]*)
You can try this.Replace by ?$1.See demo.
https://regex101.com/r/mT0iE7/28
The resultant string will not be exactly same as you want but you can easily do a clean up.
\?(?=\?)
Replace by empty string and you have what you want.See demo.
https://regex101.com/r/mT0iE7/29

What is name of a variable within a variable

I'm assigning a series of regex's to vars. Some of the regex values will be the same but unique and be identifiable by the var name itself ($a and $c as example).
#various regex
$a = "([\d]{1,2})"
$b = "([\d]{3})"
$c = $b #Note this has the same regex as $b
$d = "\s[-]\s"
$e = "[_]"
#select the pattern
$patternNum = 4
I then want to be able to concat the vars in different orders to create a larger regex.
Switch ($patternNum){
#create a pattern
1 { $pattern = ($a, $e, $b) }
2 { $pattern = ($a, $d, $b) }
3 { $pattern = ($a, $d, $a, $e, $b) }
4 { $pattern = ($a, $e, $b, $e, $c) }
}
This creates the expanded regex string i'm hoping for
#so i can use full regex pattern later
$selectedPattern = -join $pattern
But I want to be able to associate the var in $pattern with the original var name and not the literal string that's associated with the var (as some strings will be the same)
#find the index of each var and assign to another var so var can be used later to identify position within match
var1 = [array]::IndexOf($pattern, $a) # [0]
var2 = array]::IndexOf($pattern, $b) # [2]
var3 = [array]::IndexOf($pattern, $c) # [2] but i want it to be [4]
The regex which will be used in matching, each match will be used in different strings and in different positions
I thought i'd be able to use scriptblock {} and then convert back to string but that doesn't seem to work. Can anybody think of a way to get each vars original var name or think of a better way of doing this?
Using named captures
Use (? ) syntax to create named captures. Make the name the same as your variable names, e.g.:
$A = '(?<A>\d{3})'
$B = '(?<B>\D{3})'
$string = 'ABC123'
$regex = $B + $A
$string -match $regex
$Matches
Name Value
---- -----
A 123
B ABC
0 ABC123
Now you can correlate the variables to the position they matched in the string like this:
$string.IndexOf($Matches.A)
3
$string.IndexOf($Matches.B)
0
following your code I'll do it like this, but knowing what's is your real need someone can suggest other solution:
$c = $b
$d = "\s[-]\s"
$e = "[_]"
#select the pattern
$patternNum = 4
Switch ($patternNum){
#create a pattern
1 { $pattern = ('$a', '$e', '$b') }
2 { $pattern = ('$a', '$d', '$b') }
3 { $pattern = ('$a', '$d', '$a', '$e', '$b') }
4 { $pattern = ('$a', '$e', '$b', '$e', '$c') }
}
$selectedPattern = -join $pattern
$var1 = [array]::IndexOf($pattern, '$a') # [0]
$var2 = [array]::IndexOf($pattern, '$b') # [2]
$var3 = [array]::IndexOf($pattern, '$c') # [4]
#converting literal to your pattern
$regexpattern = $ExecutionContext.InvokeCommand.ExpandString( -JOIN $pattern )
$regexpattern
([\d]{1,2})[_]([\d]{3})[_]([\d]{3})

Can one use regex to wildcard a set of whole words in Perl?

This is nuts, I mean pseudocode, but something like this:
/[January, February, March] \d*/
Should match things like January 13 or February 26, and so on...
WHAT I'M DOING:
my $url0 = 'http://www.registrar.ucla.edu/calendar/acadcal13.htm';
my $url1 = 'http://www.registrar.ucla.edu/calendar/acadcal14.htm';
my $url2 = 'http://www.registrar.ucla.edu/calendar/acadcal15.htm';
my $url3 = 'http://www.registrar.ucla.edu/calendar/acadcal16.htm';
my $url4 = 'http://www.registrar.ucla.edu/calendar/acadcal17.htm';
my $url5 = 'http://www.registrar.ucla.edu/calendar/sumcal.htm';
my $document0 = get($url0);
my $document1 = get($url1);
my $document2 = get($url2);
my $document3 = get($url3);
my $document4 = get($url4);
my $document5 = get($url5);
my #dates0 = ($document0 =~ /(January|February|March|April|May|June|July|August|September|October|November|December) \d+/g);
my #dates1 = ($document1 =~ /(January|February|March|April|May|June|July|August|September|October|November|December) \d+/g);
my #dates2 = ($document2 =~ /(January|February|March|April|May|June|July|August|September|October|November|December) \d+/g);
my #dates3 = ($document3 =~ /(January|February|March|April|May|June|July|August|September|October|November|December) \d+/g);
my #dates4 = ($document4 =~ /(January|February|March|April|May|June|July|August|September|October|November|December) \d+/g);
my #dates5 = ($document5 =~ /(January|February|March|April|May|June|July|August|September|October|November|December) \d+/g);
foreach(#dates0)
{
print "$_\r\n";
}
foreach(#dates1)
{
print "$_\r\n";
}
foreach(#dates2)
{
print "$_\r\n";
}
foreach(#dates3)
{
print "$_\r\n";
}
foreach(#dates4)
{
print "$_\r\n";
}
foreach(#dates5)
{
print "$_\r\n";
}
These printing gadgets give the following result: http://pastebin.com/7z13gBqt
This is not good:
http://tinypic.com/r/nqpapx/8
Yes. You can use an alternation.
/(January|February|March|April|May|June|July|August|September|October|November|December) \d*/
Would do that.
If you already have them in an array, then you can change the variable $LIST_SEPARATOR to string them into an alternation. And then parenthesize the whole
use English qw<$LIST_SEPARATOR>; # In line-noise: $"
my $date_regex
= do { local $LIST_SEPARATOR = '|';
qr/(?:#months) \d*/ # ?: if you don't want the capture
};
This gives you a compiled expression, which you can reuse like so:
my #dates;
while ( my $url = <DATA> ) {
my $document = get( $url );
push #dates, [ $document =~ /($date_regex)/g ];
push #dates, $date;
}
__DATA__
http://www.registrar.ucla.edu/calendar/acadcal13.htm
http://www.registrar.ucla.edu/calendar/acadcal14.htm
http://www.registrar.ucla.edu/calendar/acadcal15.htm
http://www.registrar.ucla.edu/calendar/acadcal16.htm
http://www.registrar.ucla.edu/calendar/acadcal17.htm
http://www.registrar.ucla.edu/calendar/sumcal.htm

Amazon API change store

I've got the Amazon API, it works fine. But the output is alway from the US store (amazon.com) but I would like to have it from the UK store (amazon.co.uk) how should I do this?
$AWSAccessKeyId = "KEYID";
$SecretAccessKey = "ACCESKEY";
$ItemId = "12345"; // ASIN and ISBN10 or ISBN13
if(strlen($ItemId)>=13){
$ItemId = isbn13to10($ItemId);
}
$Timestamp = gmdate("Y-m-d\TH:i:s\Z");
$Timestamp = str_replace(":", "%3A", $Timestamp);
$ResponseGroup = "ItemAttributes,Offers,Images,Reviews";
$ResponseGroup = str_replace(",", "%2C", $ResponseGroup);
$String = "AWSAccessKeyId=$AWSAccessKeyId&AssociateTag=notUsed&";
$String .= "ItemId=$ItemId&
Operation=ItemLookup&
ResponseGroup=Offers&
Service=AWSECommerceService&";
$String .= "Timestamp=$Timestamp&
Version=2009-01-06";
$String = str_replace("\n", "", $String);
$Prepend = "GET\nwebservices.amazon.com\n/onca/xml\n";
$PrependString = $Prepend . $String;
$Signature = base64_encode(hash_hmac("sha256", $PrependString, $SecretAccessKey, True));
$Signature = str_replace("+", "%2B", $Signature);
$Signature = str_replace("=", "%3D", $Signature);
$BaseUrl = "http://webservices.amazon.com/onca/xml?";
$SignedRequest = $BaseUrl . $String . "&Signature=" . $Signature;
$XML = simplexml_load_file($SignedRequest);
Ahh, that was easy... So easy that one wouldn't expect it...
$Prepend = "GET\nwebservices.amazon.co.uk\n/onca/xml\n";
$BaseUrl = "http://webservices.amazon.co.uk/onca/xml?";

perl - split string into 2-character groups [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How can I split a string into chunks of two characters each in Perl?
I wanted to split a string into an array grouping it by 2-character pieces:
$input = "DEADBEEF";
#output = split(/(..)/,$input);
This approach produces every other element empty.
$VAR1 = '';
$VAR2 = 'DE';
$VAR3 = '';
$VAR4 = 'AD';
$VAR5 = '';
$VAR6 = 'BE';
$VAR7 = '';
$VAR8 = 'EF';
How to get a continuous array?
$VAR1 = 'DE';
$VAR2 = 'AD';
$VAR3 = 'BE';
$VAR4 = 'EF';
(...other than getting the first result and removing every other row...)
you can easily filter out the empty entries with:
#output = grep { /.+/ } #output ;
Edit:
You can obtain the same thing easier:
$input = "DEADBEEF";
my #output = ( $input =~ m/.{2}/g );
Edit 2 another version:
$input = "DEADBEEF";
my #output = unpack("(A2)*", $input);
Regards
Try this:
$input = "DEADBEEF";
#output = ();
while ($input =~ /(.{2})/g) {
push #output, $1;
}