how to replace EDI characters in perl to get the desired output - perl

I want to replace this string:
#N9*BM*MSCUMF036299#
with:
#N9*BM*MF036299#
in perl.
I have tried this but it has not worked.
#!/usr/bin/perl
$string = "#N9*BM*MSCUMF036299#";
$string =~ s/"N9.BM.MSCU"/"N9*BM*"/;
print "$string\n";

I have tried this but it has not worked.
$string = "#N9*BM*MSCUMF036299#";
$string =~ s/"N9.BM.MSCU"/"N9*BM*"/;
Since you used double quotes around the literal string, an undefined array variable #N9 was interpolated, yielding $string = "*BM*MSCUMF036299#". To avoid that, use single quotes.
Besides that, the quotes in s/"N9.BM.MSCU"/"N9*BM*"/ are out of place.
Correct:
$string = '#N9*BM*MSCUMF036299#';
$string =~ s/N9.BM.MSCU/N9*BM*/;

Related

how to extract the subset from a special character string using perl

I need to get the subset of a string starting from a specific start word and end before the specified word. Store in the string variable.
Example: pre-wrap">test-for??maths/camp
I need to fetch the subset.
Expected output: test-for??maths
After: pre-wrap"> or may be starting with: test
and before: /camp
I have no clue how to achieve this in Perl.
Here is the code I tried. The output is not coming as expected:
#!/usr/bin/perl
use warnings;
use strict;
my $string = 'pre-wrap">test-for??maths/camp';
my $quoted_substring = quotemeta($string);
my ($quoted_substring1) = split('/camp*', $quoted_substring);
my (undef, $substring2) = split('>\s*', $quoted_substring1);
print $string, "\n";
print $substring2, "\n";
Output:
$ perl test.pl
pre-wrap">test-for??maths/camp
test\-for\?\?maths\ # but why this \ is coming
The following code extracts the part between $before and $after (which may contain regex metacharacters, they are treated as pure characters inside the \Q...\E expressions):
my $string = 'pre-wrap">test-for??maths/camp';
my $before = 'pre-wrap">';
my $after = '/camp';
if ($string =~ /\Q$before\E(.*?)\Q$after\E/) {
print $1; # prints 'test-for??maths'
}
pre-wrap">test-for??maths/camp is in 'd',
perl -ne '/((?<=pre-wrap">)|(?<=>)(?=test))\S+(?=\/camp)/ ; print $&' d

Substitute, replace string with perl

I have string like this:
$string= "only this I need".
I am new in perl, and I tried to translate a PL/SQL code in perl.
My goal is to replace " with a blank space, finally it should look like this:
$string = only this I need
In PL/SQL I use this, and is working very well:
REGEXP_REPLACE(string,'"','');
In perl I tried this, but is not working: $string=~s/"/''; receiving an error.
Please, help me, tell me what I need to read to do my job properly?
Try this it should work:
use strict;
use warnings;
my $string= '"only this I need"';
print "$string \n"; #prints "only this I need"
$string =~ s/"/ /g;
print "$string \n"; #prints only this I need
This is a way to remove quotes from string:
my $string= '"only this I need"';
$string =~ m/"([^"]*)"/;
print "$1\n";
In case if you know the first and last character is quotes, you can do this without using regex, just use substr:
my $string= '"only this I need"';
$string = substr $string, 1, -1;
print "$string\n";

Why does 'chop' not work with <STDIN>?

I am trying to figure out why the chop function is not working for me when I try to take input from the user:
my $string = <STDIN>;
my $chr = chop($string);
print "String: $string\n";
print "Char: $chr\n";
output
perl chop.pl
hello
String: hello
Char:
But if I use a string, then it works!
my $string = "frong";
my $chr = chop($string);
print "String: $string\n";
print "Char: $chr\n";
output
[583]
perl chop.pl
String: fron
Char: g
When you pass input from console, chop is chopping the newline that is at the end of the string, which is present when you hit Enter. While your string does not contain that.
What you're chop()'ing is the newline at the end of the string. To remove the newline upon assignment from STDIN:
chomp(my $string = <STDIN>);
In other words, your program should look like this:
chomp(my $string = <STDIN>);
my $chr = chop($string);
print "String: $string\n";
print "Char: $chr\n";
Checking the perl documentation for these two functions chop and chomp might just do.
chomp
chomp This safer version of "chop" removes any trailing string that
corresponds to the current value of $/ (also known as
$INPUT_RECORD_SEPARATOR in the "English" module.
chop
chop Chops off the last character of a string and returns the
character chopped.
Hope this help
If you're printing diagnostics to show variable contents, put some form of delimiter around them, then you'd see the newline in your $chr example.
eg.
print "String: \"$string\"\n";
print "Char: \"$chr\"\n";

Split on comma, but only when not in parenthesis

I am trying to do a split on a string with comma delimiter
my $string='ab,12,20100401,xyz(A,B)';
my #array=split(',',$string);
If I do a split as above the array will have values
ab
12
20100401
xyz(A,
B)
I need values as below.
ab
12
20100401
xyz(A,B)
(should not split xyz(A,B) into 2 values)
How do I do that?
use Text::Balanced qw(extract_bracketed);
my $string = "ab,12,20100401,xyz(A,B(a,d))";
my #params = ();
while ($string) {
if ($string =~ /^([^(]*?),/) {
push #params, $1;
$string =~ s/^\Q$1\E\s*,?\s*//;
} else {
my ($ext, $pre);
($ext, $string, $pre) = extract_bracketed($string,'()','[^()]+');
push #params, "$pre$ext";
$string =~ s/^\s*,\s*//;
}
}
This one supports:
nested parentheses;
empty fields;
strings of any length.
Here is one way that should work.
use Regexp::Common;
my $string = 'ab,12,20100401,xyz(A,B)';
my #array = ($string =~ /(?:$RE{balanced}{-parens=>'()'}|[^,])+/g);
Regexp::Common can be installed from CPAN.
There is a bug in this code, coming from the depths of Regexp::Common. Be warned that this will (unfortunately) fail to match the lack of space between ,,.
Well, old question, but I just happened to wrestle with this all night, and the question was never marked answered, so in case anyone arrives here by Google as I did, here's what I finally got. It's a very short answer using only built-in PERL regex features:
my $string='ab,12,20100401,xyz(A,B)';
$string =~ s/((\((?>[^)(]*(?2)?)*\))|[^,()]*)(*SKIP),/$1\n/g;
my #array=split('\n',$string);
Commas that are not inside parentheses are changed to newlines and then the array is split on them. This will ignore commas inside any level of nested parentheses, as long as they're properly balanced with a matching number of open and close parens.
This assumes you won't have newline \n characters in the initial value of $string. If you need to, either temporarily replace them with something else before the substitution line and then use a loop to replace back after the split, or just pick a different delimiter to split the array on.
Limit the number of elements it can be split into:
split(',', $string, 4)
Here's another way:
my $string='ab,12,20100401,xyz(A,B)';
my #array = ($string =~ /(
[^,]*\([^)]*\) # comma inside parens is part of the word
|
[^,]*) # split on comma outside parens
(?:,|$)/gx);
Produces:
ab
12
20100401
xyz(A,B)
Here is my attempt. It should handle depth well and could even be extended to include other bracketed symbols easily (though harder to be sure that they MATCH). This method will not in general work for quotation marks rather than brackets.
#!/usr/bin/perl
use strict;
use warnings;
my $string='ab,12,20100401,xyz(A(2,3),B)';
print "$_\n" for parse($string);
sub parse {
my ($string) = #_;
my #fields;
my #comma_separated = split(/,/, $string);
my #to_be_joined;
my $depth = 0;
foreach my $field (#comma_separated) {
my #brackets = $field =~ /(\(|\))/g;
foreach (#brackets) {
$depth++ if /\(/;
$depth-- if /\)/;
}
if ($depth == 0) {
push #fields, join(",", #to_be_joined, $field);
#to_be_joined = ();
} else {
push #to_be_joined, $field;
}
}
return #fields;
}

Perl: function to trim string leading and trailing whitespace

Is there a built-in function to trim leading and trailing whitespace such that trim(" hello world ") eq "hello world"?
Here's one approach using a regular expression:
$string =~ s/^\s+|\s+$//g ; # remove both leading and trailing whitespace
Perl 6 will include a trim function:
$string .= trim;
Source: Wikipedia
This is available in String::Util with the trim method:
Editor's note: String::Util is not a core module, but you can install it from CPAN with [sudo] cpan String::Util.
use String::Util 'trim';
my $str = " hello ";
$str = trim($str);
print "string is now: '$str'\n";
prints:
string is now 'hello'
However it is easy enough to do yourself:
$str =~ s/^\s+//;
$str =~ s/\s+$//;
There's no built-in trim function, but you can easily implement your own using a simple substitution:
sub trim {
(my $s = $_[0]) =~ s/^\s+|\s+$//g;
return $s;
}
or using non-destructive substitution in Perl 5.14 and later:
sub trim {
return $_[0] =~ s/^\s+|\s+$//rg;
}
According to this perlmonk's thread:
$string =~ s/^\s+|\s+$//g;
Complete howto in the perfaq here:
http://learn.perl.org/faq/perlfaq4.html#How-do-I-strip-blank-space-from-the-beginning-end-of-a-string-
For those that are using Text::CSV I found this thread and then noticed within the CSV module that you could strip it out via switch:
$csv = Text::CSV->new({allow_whitespace => 1});
The logic is backwards in that if you want to strip then you set to 1. Go figure. Hope this helps anyone.
One option is Text::Trim:
use Text::Trim;
print trim(" example ");
Apply: s/^\s*//; s/\s+$//; to it. Or use s/^\s+|\s+$//g if you want to be fancy.
I also use a positive lookahead to trim repeating spaces inside the text:
s/^\s+|\s(?=\s)|\s+$//g
No, but you can use the s/// substitution operator and the \s whitespace assertion to get the same result.