Need help creating a simple regex in Perl - regex

I'm still useless when it comes to creating regex patterns. This one has got to be really easy.
Given the string: /home/users/cheeseconqueso/perl.pl
I want to place the string ./ right in front of the very last / in the original string to produce: /home/users/cheeseconqueso/./perl.pl
Thanks in advance - I'm sure this simple example will help me for a lot of other stupid stuff that shouldn't be up here!

Here's my solution based on what I was thinking of when I left the comment to your question:
use strict;
use warnings;
my $str = '/home/users/cheeseconqueso/perl.pl';
my #arr = split('/',$str);
my $newstr = join('/', #arr[0..(#arr-2)], '.', $arr[-1]);
Edit: If you're really keen on using a regex, this is the simplest one I've found:
$str =~ s|(.*/)(.*)|$1./$2|;
It takes advantage of the greediness of the initial * in the first group to take every character up to the last /, then matches everything else in the second group. It's a little easier to read with the | delimiters so you avoid leaning toothpick syndrome.

my $variable = "/home/users/cheeseconqueso/perl.pl";
$variable =~ s/(.*\/)([^\/]+)$/$1\.\/$2/;

this is using File::Basename not with regex, you can use this cpan module if you find hard to write regex.
use File::Basename;
$path = '/home/users/cheeseconqueso/perl.pl';
$newpath = dirname($path) . './'.basename($path);

You actually don't need a regex, you can just split the string:
my $str='/home/users/cheeseconqueso/perl.pl';
#Array: ('','home','users','cheeseconqueso','perl.pl')
my #arr=split(/\//,$str);
my $output=join('/',#arr[0..($#arr-2)]); # '/home/users/cheeseconqueso'
$output.='/./' . $arr[$#arr]; #Pops on the '/./' and the last element of #arr.

s/(.*)\/(.*)/\1.\/\2/
As noted by CanSpice, split works fine here too.

Try this:
my $str = "/home/users/cheeseconqueso/perl.pl";
if($str =~ /^(.*)(\/)(\w+\.\w+)$/) {
$str = $1.'/.'.$2.$3;
}

Regex? We don't need no stinkin' regex.
l-value substr() to the rescue!
#!/usr/bin/perl
use warnings;
use strict;
$_ = "/home/users/cheeseconqueso/perl.pl\n";
substr($_, rindex($_, '/'), 0) = '/.';
print;

Related

Perl regular expression to get 'This text':(

for example , if i have 'Sample text':(
My $1 should be Sample text, so any string which is enclosed in ' ' and is before :(
The following will do the trick:
/'([^']*)':\(/
For example,
my $str = "'Sample text':(";
my ($match) = $str =~ /'([^']*)':\(/
or die("No match\n");
say $match; # Sample text
Here is the simplest code to answer the question:
#/usr/bin/perl
use strict;
"'Sample text':(" =~ /'(.*)':\(/;
print "$1\n"
I'm not adding anything new here but just some samples and a place for you to test it yourself and see perhaps how it works. There are two assumptions here:
No escape characters, such as 'Sam\'ple text'.
:( is directly after your string. If it's not, you'd want to do a lookahead instead.
+ requires at least one character in your string. So 'a':( would be valid but '':( would not. If you want to allow empty strings, use * instead of +.
'([^']+)':\(

How can I use regex to remove /1 or /2?

Regex gurus,
Here is the following line of code I want to parse with regex:
#ERR030882.2595 HWI-BRUNOP16X_0001:3:1:6649:5175#0/1
I want to obtain the following:
#ERR030882.2595 HWI-BRUNOP16X_0001:3:1:6649:5175#0
I have written the following regex on rubular.com:
(#.* *.)(!?(\/.))
My idea is to use negation to remove /1 by (!?(\/.)). However, this produces the entire line?
#ERR030882.2595 HWI-BRUNOP16X_0001:3:1:6649:5175#0/1
Why is (?!thisismystring) not removing /1? I googled the fire out of this, but they seemed to suggest similar things I am already trying? I deeply appreciate your help.
I think what you are trying to write is /(\#.* .*)(?=\/\d)/ (you need to escape the at sign # to prevent Perl from treating it as an array) but you need a positive look-ahead because you want to match everything up until the following characters are a slash followed by a digit.
Here is a program that demonstrates.
use strict;
use warnings;
use 5.010;
my $s = '#ERR030882.2595 HWI-BRUNOP16X_0001:3:1:6649:5175#0/1';
$s =~ /(\#.* .*)(?=\/.)/;
print $1, "\n";
But you would be much better off copying the whole string and removing the slash and everything after it, like this
use strict;
use warnings;
my $s = '#ERR030882.2595 HWI-BRUNOP16X_0001:3:1:6649:5175#0/1';
(my $fixed = $s) =~ s{/\d+$}{};
print $fixed, "\n";
output
#ERR030882.2595 HWI-BRUNOP16X_0001:3:1:6649:5175#0

Replace using Perl

I just want to remove double quotes(") of a string "dropDownStorePrepare(this,\'hello\')".
Tried this way but not working.
#!/usr/bin/perl
use strict;
use warnings;
my $str = '"store":"dropDownStorePrepare(this,\'hello\')","name":"Rama Rao"';
$str =~ s/"dropDownStorePrepare(.*)"/dropDownStorePrepare$1/ig;
print $str;
Double quotes which are at the beginning and ending of the dropDownStorePrepare(,,,) should be removed and rest of the double quotes should be remained.
Note: dropDownStorePrepare function should accept any no of parameters.
Can somebody help me please..
The immediate problem you've got is that the .* is matching too much. Try:
$str =~ s/"dropDownStorePrepare(.*?)"/dropDownStorePrepare$1/ig;
Though it looks like you're trying to parse JSON. Maybe you should look for a module to do that for you…
Try non greedy regex,
$str =~ s/"dropDownStorePrepare(.*?)"/dropDownStorePrepare$1/ig;

Perl regular expression - eliminate

Am a newbie here. I use glimpse in my Perl script to get the path of files.
For example
/home/user/Proj/A/Apps/App.pm
/home/user/Proj/B/Apps.pm
I need to fetch the part after Proj i.e; the output should be
A/Apps/App.pm
B/Apps.pm
If you want to use regex/replace you could do something like:
$str =~ s!.*/Proj/!!;
You have various options here. When it's always at /home/user/Proj/, I prefer the second way. If not, you can use the first way as well. The best way is a substr (when its a static length):
use 5.014;
use strict;
use warnings;
my $s_a = "/home/user/Proj/A/Apps/App.pm";
my $s_b = "/home/user/Proj/B/Apps.pm";
say $s_a =~ s{.*Proj/}{}r;
say $s_b =~ s{.*Proj/}{}r;
say $s_a =~ s{/home/user/Proj/}{}r;
say $s_b =~ s{/home/user/Proj/}{}r;
say substr $s_a, 16;
say substr $s_b, 16;
output:
A/Apps/App.pm
B/Apps.pm
A/Apps/App.pm
B/Apps.pm
A/Apps/App.pm
B/Apps.pm
If you want to modifiy an existing variable to remove the first part of the path then it's simple: just use the substitution operator s/// to remove the first part of the string up to /Proj/. I've used alternative delimiters s||| here to avoid having to escape the slashes in the pattern.
use strict;
use warnings;
my #paths = qw{
/home/user/Proj/A/Apps/App.pm
/home/user/Proj/B/Apps.pm
};
for my $path (#paths) {
$path =~ s|.*/Proj/||;
print $path, "\n";
}
output
A/Apps/App.pm
B/Apps.pm
But if you want to leave your path variable as it is and copy the tail portion to another variable, then I think it's best to use a regular expression to capture the wanted part, like this
for my $path (#paths) {
my ($tail) = $path =~ m|/Proj/(.+)|;
print $tail, "\n";
}
The output is identical.

Perl Regular expression to replace the last matching string

I have a string as below:
$str = "/dir1/dir2/dir3/file.txt"
I want to remove the /file.txt from this string.
So that the $str will become.
$str = "/dir1/dir2/dir3"
I am using the following regex. But it is replacing everything.
$str =~ s/\/.*\.txt//;
How can I make regex to look for last '/' instead of first.
What is the correct regular expression for this?
Please note that file.txt is not fixed name. It can be anything like file1.txt, file2.txt, etc.
If you want to get the path from that string, you can use File::Basename. It is a core module since Perl version 5.
perl -MFile::Basename -le '$str = "/dir2/dir3/file.txt"; print dirname($str);'
In script form:
use strict;
use warnings; # always use these
use File::Basename;
my $str = "/dir1/dir2/dir3/file.txt";
print dirname($str);"
Your regex does not work because it is not anchored, and .* is greedy, so it matches as much as it can, starting from the first slash / it encounters. A working regex would look something like these:
$str =~ s#/[^/]*?\.txt$##;
Note the use of a non-greedy quantifier *?, which will match smallest possible string. Also note that I use another delimiter for the substitution to avoid the "leaning toothpick syndrome", e.g. s/\/\/\///.
Very simple regex : s/\/[^\/]*$//
In this regex
m/(.*)\/[^\/]*$/
the first submatch is the path you are looking for.
EDIT:
If you are looking for substitution user1215106's soultion is the way to go:
s/\/[^\/]*$//