How to decode ° to degree ASCII character in perl - perl

I have tried using :
my $nomIHMBloc = $1;
print decode_entities($nomIHMBloc), "\n";
$nomIHMBloc = decode_entities($nomIHMBloc), "\n";
but no luck. Is there any thing wrong? I got error:
Undefined subroutine &main::decode_entities called at "same perl file"
Thanks for your help.
PS:
exact code goes here:
while($blocVars =~ m/\[(.*?)\]/g){
binmode STDOUT, ':utf8';
my $nomIHMBloc = $1;
print decode_entities($nomIHMBloc), "\n";
$nomIHMBloc = decode_entities($nomIHMBloc);
print "nomIHMBloc::::::::$nomIHMBloc=============$1\n";
print "insert into ASSOC_VAR_BLOC (ID_BLOC, ID_VAR, DOC_ID_MAQUETTAGE) VALUES ($id_bloc, (SELECT ID_VAR FROM VARIABLE WHERE NOM_IHM='$nomIHMBloc'),'$docId')\n";
}

Works fine here:
#!/usr/bin/env perl
use strict;
use warnings;
use open ':locale';
use HTML::Entities;
# example text
'42°' =~ /(.*)/; # 42°
# your code
my $nomIHMBloc = $1;
print decode_entities($nomIHMBloc), "\n";
#$nomIHMBloc = decode_entities($nomIHMBloc), "\n";
Your last line contained syntax errors. If you want to append a newline while assigning to a scalar, use the string concatenation operator ..
$nomIHMBloc = decode_entities($nomIHMBloc) . "\n";
It works on print because it's a list operator and takes a list of arguments, then joins them with the output field separator $, (see perlvar), which contains the empty string by default and acts like a simple string concatenation. However, output is
42°

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

Split, insert and join

Here's I want to archive. I want to split a one-liner comma-separated and insert #domain.com then join it back as comma-separated.
The one-liner contains something like:
username1,username2,username3
and I want to be something like:
username1#domain.com,username2#domain.com,username3#domain.com
So my Perl script that I tried which doesn't not work properly:
my $var ='username1,username2,username3';
my #tkens = split /,/, $var;
my #user;
foreach my $tken (#tkens) {
push (#user, "$tken\#domain.com");
}
my $to = join(',',#user);
Is there any shortcut on this in Perl and please post sample please. Thanks
Split, transform, stitch:
my $var ='username1,username2,username3';
print join ",", map { "$_\#domain.com" } split(",", $var);
# ==> username1#domain.com,username2#domain.com,username3#domain.com
You could also use a regular expression substitution:
#!/usr/bin/perl
use strict;
use warnings;
my $var = "username1,username2,username3";
# Replace every comma (and the end of the string) with a comma and #domain.com
$var =~ s/$|,/\#domain.com,/g;
# Remove extra comma after last item
chop $var;
print "$var\n";
You already have good answers. Here I am just telling why your script is not working. I didn't see any print or say line in your code, so not sure how you are trying to print something. No need of last line in your program. You can simply suffix #domain.com with each value, push to an array and print it with join.
#!/usr/bin/perl
use strict;
use warnings;
my $var = 'username1,username2,username3';
my #tkens = split ',', $var;
my #user;
foreach my $tken (#tkens)
{
push #user, $tken."\#domain.com"; # `.` after `$tken` for concatenation
}
print join(',', #user), "\n"
Output:
username1#domain.com,username2#domain.com,username3#domain.com

Splitting Perl string and adding _ in between

Question. I am trying to read in perl string from command line e.g. "abcdef" and then split this into "a_b_c_d_e_f".
I am struggling with logic part. any ideas?
#!/usr/bin/perl
while($line=<STDIN>){
chomp $line;
split $line;
join ("_", $line);
print $line;
}
The split manpage actually includes exactly this example:
print join(':', split('', 'abc')), "\n";
Adjusting to use _ instead of : and $line instead of 'abc', we get:
print join('_', split('', $line)), "\n";
The most important point is that split doesn't modify its arguments, it just returns a list, and join doesn't modify its arguments, it just returns a string. So it never makes sense to call split or join without using the return-value.
What you need is
print join('_', split //, $line), "\n";
One-liner:
print join('_', split('', $line)), '\n';
You can read more about perl's split() function here.
Unless you must use split, you can use a between-character substitution for this:
use strict;
use warnings;
my $string = 'abcdef';
$string =~ s/(?<=.)(?:)(?=.)/_/g;
print $string;
Output:
a_b_c_d_e_f
Hope this helps!

Print only the first word in line

I need some help with following perl code.
#!perl -w
use strict;
use warnings;
open my $file, '<', 'ubb' or die $1;
my $spool = 0;
my #matchingLines;
while (<$file>) {
if (/GROUPS/i) {
$spool = 1;
next;
}
elsif (/SERVERS/i) {
$spool = 0;
print map { "$_" } #matchingLines;
#matchingLines = ();
}
if ($spool) {
push (#matchingLines, $_);
}
}
close ($file);
Output from that is shown below.
ADM LMID=GW_S4_1_PM,GW_S4_2_BM
GRPNO=1
ADM_TMS LMID=GW_S4_1_PM,GW_S4_2_BM
GRPNO=2
TMSNAME=TMS
ADM_1 LMID=GW_S4_1_PM
GRPNO=11
ADM_2 LMID=GW_S4_2_BM
GRPNO=12
DMWSG_Gateway_1 LMID=GW_S4_1_PM
GRPNO=101
ENVFILE="../GW_S4.Gateway.envfile"
DMWSG_Gateway_2 LMID=GW_S4_2_BM
GRPNO=201
ENVFILE="../GW_S4.Gateway.envfile"
DMWSG_1 LMID=GW_S4_1_PM
GRPNO=106
DMWSG_2 LMID=GW_S4_2_BM
GRPNO=206
But I only would like to get the first word of each line (e.g. ADM, ADM_TMS, ADM_1).
Note that the file has a lot of other lines above and below what's printed here. I only want to do this for lines that is in between GROUPS and SERVERS.
I would suggest 2 changes in your code
Note: Tested these with your sample data (plus other stuff) in your question.
I: Extract first word before push
Change this
push (#matchingLines, $_);
to
push (#matchingLines, /^(\S+)/);
This would push the first word of each line into the array, instead of the entire line.
Note that /^(\S+)/ is shorthand for $_ =~ /^(\S+)/. If you're using an explicit loop variable like in 7stud's answer, you can't use this shorthand, use the explicit syntax instead, say $line =~ /^(\S+)/ or whatever your loop variable is.
Of course, you can also use split function as suggested in 7stud's answer.
II: Change how you print
Change this
print map { "$_" } #matchingLines;
into
local $" = "\n";
print "#matchingLines \n";
$" specifies the delimiter used for list elements when the array is printed with print or say inside double quotes.
Alternatively, as per TLP's suggestion,
$\ = $/;
print for #lines;
or
print join("\n", #lines), "\n"
Note that $/ is the input record separator (newline by default), $\ is the output record separator (undefined by default). $\ is appended after each print command.
For more information on $/, $\, and $":
See perldoc perlvar (just use CTRL+F to find them in that page)
Or you can simply use perldoc -v '$/' etc on your console to get those information.
Note on readability
I don't think implicit regex matching i.e. /pattern/ is bad per se.
But matching against a variable, i.e. $variable =~ /pattern/ is more readable (as in you can immediately see there's a regex matching going on) and more beginner-friendly, at the cost of conciseness.
use strict;
use warnings;
use 5.014; #say()
my $fname = 'data.txt';
open my $INFILE, '<', $fname
or die "Couldn't open $fname: $!"; #-->Not $1"
my $recording_on = 0;
my #matching_lines;
for my $line (<$INFILE>) {
if ($line =~ /groups/i) {
$recording_on = 1;
next;
}
elsif ($line =~ /servers/i) {
say for #matching_lines; #say() is the same as print(), but it adds a newline at the end
#matching_lines = ();
$recording_on = 0;
}
if ($recording_on) {
my ($first_word, $trash) = split " ", $line, 2;
push #matching_lines, $first_word;
}
}
close $INFILE;
You can use the flip-flop operator (range) to select a part of your input. The idea of this operator is that it returns false until its LHS (left hand side) returns true, and after that it returns true until its RHS returns false, after which it is reset. It is somewhat like preserving a state.
Note that the edge lines are also included in the match, so we need to remove those. After that, use doubleDown's idea and push /^(\S+)/ onto an array. The nice thing about using this with push is that the capture regex returns an empty list if it fails, and this gives us a warning-free failure when the regex does not match.
use strict;
use warnings;
my #matches;
while (<>) {
if (/GROUPS/i .. /SERVERS/i) { # flip-flop remembers the matches
next if (/GROUPS/i or /SERVERS/i);
push #matches, /^(\S+)/;
}
}
# #matches should now contain the first words of those lines

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";