perl blank substitution in a string - perl

I have this two kind of strings:
EVASA 2144
IN ELABORAZIONE 16278
I need some perl script to substitute all the blanks with just one.
The output I need is:
EVASA 2144
Any suggestion?

You can use a very simple regex:
#!/usr/bin/perl
use strict;
my $line = 'EVASA 2144';
# This is the line that actually does the work
$line =~ s/\s+/ /g;
print $line, "\n";

My suggestion would be that you spend some time reading the Regular Expression tutorial that is distributed with every modern version of Perl.

$a = "hello \t world";
$a =~ s/\s+/ /;
print $a;
if you may have multiple places in the string where you want the substitution to take place, use
$a = "hello \t world hi";
$a =~ s/\s+/ /g;
print $a;

You can also use the troperator with the s Option, this can do more things for you (transforming characters), probably faster than the regexp approach
$a =~ tr/ \t/ /s;
Explanation can be found in the perlop manpage:
perldoc perlop

Related

Why is chomp not removing whitespace around my string?

I don't understand why perl chomp isn't removing the whitespace surrounding my string. I've even tried to call chomp twice, for example, using bash:
$ perl -e 'use 5.22.4; chomp(my $extra=" lol "); chomp($extra); say "<$extra>"'
< lol >
I really expected to get
<lol>
Chomp only removes the line ending (can be set with $/ variable) from the end of the string. It does not trim the string. Perl does not have a built-in trim function. I usually spell out two substitutions instead:
s/^\s+//, s/\s+$// for $string;
Further reading:
perldoc -f chomp
Perl FAQ: How do I strip blank space from the beginning/end of a string?
To remove all whitespace:
$string =~ s/\s+//g;
Left trim:
$string =~ s/^\s+//;
Right Trim:
$string =~ s/\s+$//;
Left and Right trim:
$string =~ s/^\s+|\s+$//g
We can then also build trimming fucntions. This helps in much bigger scripts where you would not want to write the full replacement strings each time, we write them once, then use the function to do the work.
This simple function can be used in any script as trim($string);
sub trim {
$_[0] =~ s/^\s+|\s+$//g;
}
Similarly with a full strip of whitespace.
sub full_strip {
$_[0] =~ s/\s+//g;
}
in a script:
use strict;
use warnings;
my $string = " this is line with leading and trailing whitespaces ";
my $string2 = " another one of those lines ";
trim($string);
trim($string2);
print "$string\n";
print "$string2\n";
full_strip($string);
full_strip($string2);
print "$string\n";
print "$string2\n";
sub trim {
$_[0] =~ s/^\s+|\s+$//g;
}
sub full_strip {
$_[0] =~ s/\s+//g;
}
$string=~s/^\s+|\s+$//g;
This would work well for any generic string where you want to remove beginning and ending spaces.

Unmatched ) in reg when using lc function

I am trying to run the following code:
$lines = "Enjoyable )) DAY";
$lines =~ lc $lines;
print $lines;
It fails on the second line where I get the error mentioned in the title. I understand the brackets are causing the trouble. I think I could use "quotemeta", but the thing is that my string contains info that I go on to process later, so I would like to keep the string intact as far as possible and not tamper with it too much.
You have two problems here.
1. =~ is used to execute a specific set of operations
The =~ operator is used to either match with //, m//, qr// or a string; or to substitute with s/// or tr///.
If all you want to do is lowercase the contents of $lines then you should use = not =~.
$lines = "Enjoyable )) DAY";
$lines = lc $lines;
print $lines;
2. Regular expressions have special characters which must be escaped
If you want to match $lines against a lower case version of $Lines, which should return true if $lines was already entirely lower case and false otherwise, then you need to escape the ")" characters.
#!/usr/bin/env perl
use strict;
use warnings;
my $lines = "enjoyable )) day";
if ($lines =~ lc quotemeta $lines) {
print "lines is lower case\n";
}
print $lines;
Note this is a toy example trying to find a reason for doing $lines =~ lc $lines - It would be much better (faster, safer) to solve this with eq as in $lines eq lc $lines.
See perldoc -f quotemeta or http://perldoc.perl.org/functions/quotemeta.html for more details on quotemeta.
=~ is used for regular expressions. "lc" is not part of regex, it's a function like this: $new = lc($old);
I don't recall the regex operator for lowercase, because I use lc() all the time.

Perl: long string conversion to comma delimited list of bytes

I want to convert ABCDEF to A,B,C,D,E,F
What is the fastest way to do this using Perl?
I have lots of strings to convert and the strings can be up to 32768 bytes long. So, I want to lower the overhead from the string conversion.
How about
$string =~ s/.\K(?=.)/,/g; # using \K keep escape
$string =~ s/(?<=.)(?=.)/,/g; # pure lookaround assertion
Or
$string = join ",", split(//, $string);
To find the fastest solution, use Benchmark.
Extra credit:
This is the result of a benchmark I tried. Surprisingly, the \K escape is much faster than the pure lookaround, which is about as fast as the split/join.
use strict;
use warnings;
use Benchmark qw(cmpthese);
my $string = "ABCDEF" x 1000;
cmpthese(-1, {
keep => 'my $s = $string; $s =~ s/.\K(?=.)/,/g',
lookaround => 'my $s = $string; $s =~ s/(?<=.)(?=.)/,/g',
splitjoin => 'my $s = $string; $s = join ",", split(//, $string)'
});
Output:
Rate splitjoin lookaround keep
splitjoin 6546367/s -- -6% -47%
lookaround 6985568/s 7% -- -44%
keep 12392841/s 89% 77% --
$ perl -le 'print join(",", unpack("(A)*", "hello"))'
h,e,l,l,o
$ perl -le 'print join(",", unpack("C*", "hello"))'
104,101,108,108,111
$ perl -le 'print join(",", unpack("(H2)*", "hello"))'
68,65,6c,6c,6f
my $str = "ABCDEFGHIJKL";
my #chars = $str =~ /./sg;
print join ",", #chars;
If you're trying to print strings with lower overhead, you may want to just print the string while you parse it, rather than doing the whole transformation in memory, i.e.
while (m/(.)\B/gc){
print "$1,";
};
if (m/\G(.)/) {
print "$1\n";
}

Check for spaces in perl using regex match in perl

I have a variable how do I use the regex in perl to check if a string has spaces in it or not ? For ex:
$test = "abc small ThisIsAVeryLongUnbreakableStringWhichIsBiggerThan20Characters";
So for this string it should check if any word in the string is not bigger than some x characters.
#!/usr/bin/env perl
use strict;
use warnings;
my $test = "ThisIsAVeryLongUnbreakableStringWhichIsBiggerThan20Characters";
if ( $test !~ /\s/ ) {
print "No spaces found\n";
}
Please make sure to read about regular expressions in Perl.
Perl regular expressions tutorial - perldoc perlretut
You should have a look at the perl regex tutorial. Adapting their very first "Hello World" example to your question would look like this:
if ("ThisIsAVeryLongUnbreakableStringWhichIsBiggerThan20Characters" =~ / /) {
print "It matches\n";
}
else {
print "It doesn't match\n";
}
die "No spaces" if $test !~ /[ ]/; # Match a space
die "No spaces" if $test =~ /^[^ ]*\z/; # Match non-spaces for entire string
die "No whitespace" if $test !~ /\s/; # Match a whitespace character
die "No whitespace" if $test =~ /^\S*\z/; # Match non-whitespace for entire string
To find the length of the longest unbroken sequence of non-space characters, write this
use strict;
use warnings;
use List::Util 'max';
my $string = 'abc small ThisIsAVeryLongUnbreakableStringWhichIsBiggerThan20Characters';
my $max = max map length, $string =~ /\S+/g;
print "Maximum unbroken length is $max\n";
output
Maximum unbroken length is 61

How can I replace multiple whitespace with a single space in Perl?

Why is this not working?
$data = "What is the STATUS of your mind right now?";
$data =~ tr/ +/ /;
print $data;
Use $data =~ s/ +/ /; instead.
Explanation:
The tr is the translation operator. An important thing to note about this is that regex modifiers do not apply in a translation statement (excepting - which still indicates a range). So when you use
tr/ +/ / you're saying "Take every instance of the characters space and + and translate them to a space". In other words, the tr thinks of the space and + as individual characters, not a regular expression.
Demonstration:
$data = "What is the STA++TUS of your mind right now?";
$data =~ tr/ +/ /;
print $data; #Prints "What is the STA TUS of your mind right now?"
Using s does what you're looking for, by saying "match any number of consecutive spaces (at least one instance) and substitute them with a single space". You may also want to use something like
s/ +/ /g; if there's more than one place you want the substitution to occur (g meaning to apply globally).
You can also use tr with the "squash" option, which will remove duplicate replaced characters. See perlop for details.
my $s = "foo bar fubb";
$s =~ tr/ //s;
Perl 5.10 has a new character class, \h, the stands for horizontal whitespace which is nice for this sort of thing:
$s =~ s/\h+/ /g;