Perl: No replacement of a string - string

If i replace a string in another one using something simple like this
my $pet = "I have a dog.";
my $search = "dog";
my $replace = "cat";
$pet =~ s/$search/$replace/;
it works fine and i get "I have a cat." as expected.
But when i am using something more complex like the following it doesn't get replaced:
my $image_correction_hash = {};
$device = "my_device";
$correction_hash->{$device}->{'to_be_replaced'} = "174_4492_232313_7078721ec0.jpg";
# my json string
my $json = '[{"credits":[],"issue":174,"layout":"special_cover","text":[],"hide_overline":"","category":"Kunst","id":"174_4492","media_data":[{"thumbnail":"","data_is_cover":1,"subheadline":"","value":"174_4492.jpg","type":"image","headline":""},{"data_position":"left","thumbnail":"","subheadline":"","value":"174_4492_232302_3980b3da34.jpg","data_effect":"smear","type":"image","headline":""},{"data_position":"right","thumbnail":"","subheadline":"","value":"174_4492_232313_7078721ec0.jpg","data_effect":"smear","type":"image","headline":""}],"links":[],"textmarker":"","teaser":"","hide_headline":"","article_thumbnail":"174_4492_article_thumbnail.jpg","subheadline":"","gallery":[],"overline":"","headline":"Covertitel\n"}]';
print STDERR "JSON string before:" . $json . "\n";
foreach my $search ( keys %{$correction_hash->{$device}})
{
print STDERR "to be replaced:".$correction_hash->{$device}->{$search}.".\n";
# the replacement
$json =~ s/$search/XXXXX/g;
}
print STDERR "JSON string after:" . $json . "\n"; # no replacement occured - GRRR
Where is the error here?

You mixed up your variables.
Try this:
print STDERR "to be replaced:".$search.".\n";
It will print this: to be replaced:to_be_replaced.
So you can use this code:
my $pattern = $correction_hash->{$device}->{$search};
$json =~ s/$pattern/XXXXX/g;
On a side note, if your $pattern is not a regex, you should escape it using this code:
$json =~ s/\Q$pattern\E/XXXXX/g;

You're trying to use $search in your pattern replacement, not the actual pattern you want to replace. So you're trying to replace to_be_replaced with XXXXXXXX. Not 174_4492_232313_7078721ec0.jpg.
You probably want to add:
$replace_pattern = $correction_hash->{$device}->{$search};
$json =~ s/$replace_pattern/XXXXX/g;

Related

Perl: How to pass in an input without being replaced by the substitution s/// Operator?

For example,
$test = "abc";
$test =~ s/b//g;
normally test will be ac. How do I manipulate the string "abc" so that it will go through this test and still return abc.
I am trying to do a command injection so I can't change $test =~ s/b//g; but can change the input.
Hopefully this makes sense.
You want to use the /r modifier. it's a new'ish feature so older versions will not run it
$test = "abc";
my $str= $test =~ s/b//gr;
http://perldoc.perl.org/perlre.html#Modifiers
There is no string you can pass to s/b//g that will result in a string that contains a b.
However, if you have access to $test and not just it's value, you could set its pos such that the substitution operator won't find anything.
$ perl -e'
my $test = "abc";
pos($test) = length($test);
$test =~ s/b//g;
CORE::say($test);
'
ac

Perl URL replace

I am trying to achieve following task,
Extract all urls from the text.
If domain belongs to white list, then replace them with modified urls.
Following is the code.
$text = '<img src="http://www.testurl.de/Sasdfhopr.jpg" width="80%">';
$regex = '(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,#?^=%&:\/~+#-]*[\w#?^=%&\/~+#-])?';
#whiteList = ("www.amazon.de");
while ($text =~ /$regex/g) {
# regex result has following groups as matches
# $1 = scheme
# $2 = domain
# $3 = query parameters
# check if domain is in white list
if ( grep( /^$2$/, #whiteList ) ) {
# build new url
$new = "http://test.xyz.pqr/url=".$1."://".$2.$3;
# recreate old url
$old = $1."://".$2.$3;
# replace it here, but its not replacing
$text =~ s/$old/$new/g;
# but as an example replacing
# domain name with test, its working.
# it appears to be something to with back slash or forward
# slashes
$text =~ s/$2/test/g;
}
} print $text;
Any help or hint would be great. As I am new to perl programming.
I would use Regexp::Common in conjunction with Regexp::Common::URI to locate the URLs, and
URI to parse and transform them
Your very minimal data sample doesn't help, but here is a proof of my idea using that data
use strict;
use warnings 'all';
use Regexp::Common 'URI';
use URI;
use List::Util 'any';
use constant NEW_HOST => 'test.xyz.pqr';
my $text = <<'END';
<a href="http://www.amazon.de/Lenovo-Moto-Smartphone-Android-schwarz/dp/B01FLZC8ZI">
<img src="http://www.testurl.de/Sasdfhopr.jpg" width="80%">
</a>
END
my #white_list = qw/ www.amazon.de /;
$text =~ s{ ( $RE{URI}{HTTP} ) } {
my $uri = URI->new($1);
my $host = $uri->host;
$uri->host(NEW_HOST) if any { $host eq $_ } #white_list;
$uri->as_string;
}exg;
print $text, "\n";
output
<a href="http://test.xyz.pqr/Lenovo-Moto-Smartphone-Android-schwarz/dp/B01FLZC8ZI">
<img src="http://www.testurl.de/Sasdfhopr.jpg" width="80%">
</a>
The URL in $old contains characters that Perl's regex engine treats as part of the pattern, not as literal characters, when you use it inside the pattern match.
$text =~ s/$old/$new/g;
You need to escape those. You can do that with the \Q and \E commands.
$text =~ s/\Q$old\E/$new/g;
That should do the trick, assuming the rest of your code is working, which I have not tried.

How to divide string in perl for 2 parts

so I need to divide my string in perl for 2 parts. For example I have:
$string = "../dira/dirb/*.txt"
And I want to divide it on:
$stringA = "../dira/dirb"
$stringB = "*.txt"
But if I have:
$string = "dira/dirb/dirc/.../dirn/test.pl";
I want to divie it on:
$stringA = "dira/dirb/dirc/.../dirn"
$stringB = "test.pl"
Somebody have idea how can I do it? I tried to do something like:
$howmany++ while $string =~ m/\//g;
So I know how many slashes I have. But I have no idea what I can do more with this :/
Use Path::Tiny:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Path::Tiny;
for my $path (qw( ../dira/dirb/*.txt
dira/dirb/dirc/.../dirn/test.pl
)) {
my $path_o = 'Path::Tiny'->new($path);
my $basename = $path_o->basename;
my $dirname = $path_o->dirname;
$dirname =~ s=/$==; # Remove the trailing slash.
say $basename, ' ', $dirname;
}
you can try something like this:
$string =~ m|^(.*)/(.*)$|;
($stringA,$stringB) = ($1,$2);
print "stringA = $stringA\n";
print "stringB = $stringB\n";
= edit: =
restrict to certain values of stringB:
if($string =~ m|^(.*)/(.*\.pl)$|) {
($stringA,$stringB) = ($1,$2);
print "stringA = $stringA\n";
print "stringB = $stringB\n";
}
You can use File::Basename functions to parse file paths:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Basename;
my $string = "../dira/dirb/*.txt";
my $stringA = dirname($string);
my $stringB = basename($string);
printf "String A: %-25sString B: %s\n", $stringA, $stringB;
$string = "dira/dirb/dirc/.../dirn/test.pl";
$stringA = dirname($string);
$stringB = basename($string);
printf "String A: %-25sString B: %s\n", $stringA, $stringB;

How to read "<somestring>" in input string in perl

Below is my code. It still produces same string with no "<init>"
input string :
1: invokespecial #1 // Method java/lang/Object."<init>":()V
my $file = "Hello.javap";
open my $fh, '<', $file or die "Could not open '$file' $!";
while (my $line = <$fh>) {
if (index(uc($line), uc("Code:")) != -1) {
$code_block_started=1;
}
if(index($line,":")==-1)
{
if (my ($method) = $line =~ /.* \/\/ Method (.*);/) {
print "Method: $method\n";
}
print $line;
$code_block_started=0;
}
if($code_block_started){
if ($line =~/[0-9]/) {
my #num_strip = split(':',$line);
my #get_command = split(' ',$num_strip[1]);
# print "\n $get_command[0]";
$count{$get_command[0]}++;
}
}
Are you simply asking how to escape the " in perl? If so, write \"<init>\" just like in most languages.
Are you asking for a regular expression? If so, $str ~= /.* \/\/ Method (.*);/ will put java/lang/Object."<init>":()V into $1.
while (my $str = <>) {
if (my ($method) = $str =~ m{// Method (.*)}) {
print "$method\n";
}
}
when Perl sees the double-quote just before the word "name" it thinks that was the end of the string and then it complains about the word name being a bareword.
You might have already guessed, we need to escape the embedded " character:
use strict;
use warnings;
my $name = 'foo';
print "The \"name\" is \"$name\"\n";
http://perlmaven.com/quoted-interpolated-and-escaped-strings-in-perl

Powershell format operator inside function

I've found out the format operator is working differently inside a function compared to a plain script.
Here's a simple example of what is working as expected:
[string]$name = 'Scripting Guy'
[string]$statement = 'PowerShell rocks'
$s = "The {0} thinks that {1}!" -f $name, $statement
write-host $s
producing:
The Scripting Guy thinks that PowerShell rocks!
While inside a function it does something different:
function myFunc( [string] $iname, [string] $istatement) {
$s = "The {0} thinks that {1}!" -f $iname, $istatement
write-host $s
}
[string]$name = 'Scripting Guy'
[string]$statement = 'PowerShell rocks'
myFunc($name, $statement)
produces:
The Scripting Guy PowerShell rocks thinks that !
I tried to play with it to find out what it's doing:
function myFunc( [string] $iname, [string] $istatement) {
$s = "The {0} thinks that {1}! {2} {3}" -f $iname, $istatement, "=====", $iname
write-host $s
}
[string]$name = 'Scripting Guy'
[string]$statement = 'PowerShell rocks'
myFunc($name, $statement)
This produces:
The Scripting Guy PowerShell rocks thinks that ! ===== Scripting Guy PowerShell rocks
So now I don't know what to think about this.
You should call the function as follows:
myFunc -iname "Scripting Guy" -istatement "Powershell Rocks!!"
or
myFunc $name $statement
The current method you're using passes a single array object that's why the elements get printed in succession

Resources