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

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

Related

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

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

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*/;

How to decode ° to degree ASCII character in 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°

With Perl, how do I read records from a file with two possible record separators?

Here is what I am trying to do:
I want to read a text file into an array of strings. I want the string to terminate when the file reads in a certain character (mainly ; or |).
For example, the following text
Would you; please
hand me| my coat?
would be put away like this:
$string[0] = 'Would you;';
$string[1] = ' please hand me|';
$string[2] = ' my coat?';
Could I get some help on something like this?
This will do it. The trick to using split while preserving the token you're splitting on is to use a zero-width lookback match: split(/(?<=[;|])/, ...).
Note: mctylr's answer (currently the top rated) isn't actually correct -- it will split fields on newlines, b/c it only works on a single line of the file at a time.
gbacon's answer using the input record separator ($/) is quite clever--it's both space and time efficient--but I don't think I'd want to see it in production code. Putting one split token in the record separator and the other in the split strikes me as a little too unobvious (you have to fight that with Perl ...) which will make it hard to maintain. I'm also not sure why he's deleting multiple newlines (which I don't think you asked for?) and why he's doing that only for the end of '|'-terminated records.
# open file for reading, die with error message if it fails
open(my $fh, '<', 'data.txt') || die $!;
# set file reading to slurp (whole file) mode (note that this affects all
# file reads in this block)
local $/ = undef;
my $string = <$fh>;
# convert all newlines into spaces, not specified but as per example output
$string =~ s/\n/ /g;
# split string on ; or |, using a zero-width lookback match (?<=) to preserve char
my (#strings) = split(/(?<=[;|])/, $string);
One way is to inject another character, like \n, whenever your special character is found, then split on the \n:
use warnings;
use strict;
use Data::Dumper;
while (<DATA>) {
chomp;
s/([;|])/$1\n/g;
my #string = split /\n/;
print Dumper(\#string);
}
__DATA__
Would you; please hand me| my coat?
Prints out:
$VAR1 = [
'Would you;',
' please hand me|',
' my coat?'
];
UPDATE: The original question posed by James showed the input text on a single line, as shown in __DATA__ above. Because the question was poorly formatted, others edited the question, breaking the 1 line into 2. Only James knows whether 1 or 2 lines was intended.
I prefer #toolic's answer because it deals with multiple separators very easily.
However, if you wanted to overly complicate things, you could always try:
#!/usr/bin/perl
use strict; use warnings;
my #contents = ('');
while ( my $line = <DATA> ) {
last unless $line =~ /\S/;
$line =~ s{$/}{ };
if ( $line =~ /^([^|;]+[|;])(.+)$/ ) {
$contents[-1] .= $1;
push #contents, $2;
}
else {
$contents[-1] .= $1;
}
}
print "[$_]\n" for #contents;
__DATA__
Would you; please
hand me| my coat?
Something along the lines of
$text = <INPUTFILE>;
#string = split(/[;!]/, $text);
should do the trick more or less.
Edit: I've changed "/;!/" to "/[;!]/".
Let Perl do half the work for you by setting $/ (the input record separator) to vertical bar, and then extract semicolon-separated fields:
#!/usr/bin/perl
use warnings;
use strict;
my #string;
*ARGV = *DATA;
$/ = "|";
while (<>) {
s/\n+$//;
s/\n/ /g;
push #string => $1 while s/^(.*;)//;
push #string => $_;
}
for (my $i = 0; $i < #string; ++$i) {
print "\$string[$i] = '$string[$i]';\n";
}
__DATA__
Would you; please
hand me| my coat?
Output:
$string[0] = 'Would you;';
$string[1] = ' please hand me|';
$string[2] = ' my coat?';

Why isn't Perl's tr/// doing what I want?

I am using Perl for a script that takes in input as two short strings of DNA. As an output, I concatenate the two strings strings then print the second string lined up over its copy at the end of the concatenated string. For example: if input string are AAAA and TTTTT then print:
AAAAATTTTT
TTTTT
I know there are other ways to do this but I am curious to know why my use of tr/// isn't working.
The code for the program is:
use strict;
use warnings;
print "enter a DNA sequence \n";
$DNA1=<>; #<> shorthand for STDIN
$DNA1=~ s/\r?\n?$//;
print $DNA1 "\n\n";
print "enter second DNA sequence \n";
$DNA2=<>;
$DNA2=~ s/\r?\n?$//;
print $DNA2 "\n\n";
$DNA= join("",($DNA1,$DNA2));
print "Both DNA sequences are \"$DNA\" \n\n";
$DNA3=$DNA1;
$DNA3=~ tr/ATCGatcg//;
print $DNA3 "\n\n";
$DNA4= join("",($DNA3,$DNA2));
print $DNA4 "\n\n";
exit;
Your tr changes any of ACTGatcg and removes them. I think you want
$DNA3 =~ tr/atcgATCG/ /;
You need to put a space in the second half of the tr command.
Alternatively, it seems that what you're trying to do is create a variable containing as many spaces as there were characters in the first string:
my $spaces = ' ' x length($DNA1);
It might just be a simple syntax error. Try:
$DNA3 =~ tr/ATCGatcg/ /;
where the second slash separates your two translation entities, and you have a space character between the second and third slashes.
Good luck!
Edit: my mistake - misunderstood what you wanted to do. Answer adjusted accordingly :)
Is this the program that you want?
#!perl
my $s1 = 'AAAAAAAAA';
my $s2 = 'TCGAGCTA';
print
$s1, $s2, "\n",
' ' x length( $s1 ), $s2, "\n";