bitwise shift for a string holding a numeric hex. in perl - perl

I have a string
$string = "0x0"
Now I want to basically use this string as a number and do a bitwise shift i.e my aim is to
$C = $string <<4 ;
But when I do this it says :
Argument "0x0" isn't numeric in left bitshift (<<)
Can someone please help to execute this ?

It's because "0x0" isn't numeric. It's a string. You would have to turn it into a numeric value.
use strict;
use warnings;
my $string = "0x0";
my $number = hex($string);
my $C = $number <<4 ;
print $C;

As mentioned, you have to convert it to a numeric value and use sprintf to turn back to a hexadecimal value.
sprintf ("0x%x" , hex($string) << 4);

Related

How to separate the Hex 8 bits into two 4 bits

I am using like this,
$a = "002c459f";
$b = $a%10000;
$c = int($a/10000);
print $b; #prints 0
print $c; #prints 2
I want
$b=459f;
$c=002c;
Can anyone suggest how will I get this?
If you had used warnings, you would have gotten a warning message indicating a problem.
Since your 8-bit input is already formatted as a simple hex string, you can just use substr:
use warnings;
use strict;
my $x = '002c459f';
my $y = substr $x, 0, 4;
my $z = substr $x, 4, 4;
print "z=$z, y=$y\n";
Output:
z=459f, y=002c
It is a good practice to also use strict. I changed your variable names since a and b are special variables in Perl.
You should always use use strict; use warnings;! It would have told you that 002c459f isn't a number. (It's the hex representation of a number.) As such, you can't use division before first converting it into a number. You also used the wrong divisor (10000 instead of 0x10000).
my $a_num = hex($a_hex);
my $b_num = $a_num % 0x10000; # More common: my $b_num = $a_num & 0xFFFF;
my $c_num = int( $a_num / 0x10000 ); # More common: my $c_num = $a_num >> 16
my $b_hex = sprintf("%04x", $b_num);
my $c_hex = sprintf("%04x", $c_num);
But if you have exactly eight characters, you can use the following instead:
my ($c, $b) = unpack('a4 a4', $a);
Note: You should avoid using $a and $b as it may interfere with sort and some subs.
Input data is a hex string, regular expression can be applied to split string by 4 characters into an array.
At this point you can use result as a strings, or you can use hex() to convert hex string representation into perl's internal digital representation.
use strict;
use warnings;
use feature 'say';
my $a = "002c459f"; # value is a string
my($b,$c) = $a =~ /([\da-f]{4})/gi;
say "0x$b 0x$c\tstrings"; # values are strings
$b = hex($b); # convert to digit
$c = hex($c); # convert to digit
printf "0x%04x 0x%04x\tdigits\n", $b, $c;
Output
0x002c 0x459f strings
0x002c 0x459f digits

How can I force the user to enter an integer?

I want to check that the input from the user is an integer number. I tried the following, but it doesn't work:
try {
print "Enter int";
$num=int(<>);
print "okej";
}
catch (ValueError $e{
print"not int";
}
You really do not want to punish users for leading/trailing spaces (as too many web sites these days seem to be doing), but also avoid leading zeros. Also, make sure the output is flushed before asking for input:
#!/usr/bin/env perl
use strict;
use warnings;
my $input;
until (defined $input) {
local $| = 1;
print 'Enter an integer: ';
($input) = (<STDIN> =~ /\A \s* (-? [1-9] [0-9]* ) \s* \z/x);
}
print "$input\n";
The int function does not check if something is an integer. Instead, it converts its argument to an integer. So, int(1) is 1, int(1.11) is also 1, and int('a') is 0 — with a warning if you enabled warnings.
See also:
"How do I determine whether a scalar is a number/whole/integer/float?" in perlfaq4. You should read the excellent documentation that comes with Perl.
perldoc -v '$|'
Check to see if input has only digits and nothing else...
use warnings;
use strict;
print "Enter integer: ";
my $input = <>;
chomp $input;
print "is int\n" if $input =~ /^[0-9]+$/;

How to extract the date from the string pattern in perl

How do I extract date Simple_Invoice_Report.Summary.20150701000000.csv from this string in perl?
i.e. 20150701
Can you please help me out.
The simplest solution is a regular expression match. Assuming your date is always the first 8 digits in your string:
my ( $date ) = ( $string =~ m/(\d{8})/ );
If it's more complicated than that, you'll need to be a bit more specific.
Below is the code to extract the data from the above string:
#!/usr/bin/perl
use strict;
use warnings;
my $string = q{Simple_Invoice_Report.Summary.20150701000000.csv};
if($string =~ m#.(\d{8})\d+.csv#g){
print $1;
}
Output: 20150701

Accept user input perl

How do I accept a list of integers as input? The only thing I can think of is getting each integer from the list specifically using STDIN. Is there a better way to do this?
You want input a list of integers? I take it you mean that you want to enter a list of numbers, and accept that input if they're all integers.
In this program, I loop forever until I get a valid list, thus for (;;). Some people prefer while (1).
I use Scalar::Util's looks_like_number to test whether the input is numeric, and then use int to verify that the number is an integer. You could use a regular expression like /^\d+$/, but there's no guarantee that it works in all circumstances. Using int and looks_like_number guarantees the results.
I assume that a list of integers could be space separated or comma separated or both, thus my split /[\s,]+/.
You said:
The only thing I can think of is getting each integer from the list specifically using STDIN. Is there a better way to do this?
You read in data from a file handle, whether a file or something like STDIN. No way around that. However, you can at least make it a single input rather one at a time which I assume you mean.
By the way, I could have combined my numeric test with:
if( not looks_like_number $integer or $integer != $integer ) {
Since this is an or statement, if this would first check if $input looks numeric, and if it isn't, would warn about the input before checking to see if it's an integer. However, I'm not sure this is actually clearer than making it too separate statements.
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
use Scalar::Util qw(looks_like_number);
my #integers; # Storage for my integers
#
# Keep looping until you have a valid input
#
INPUT:
for (;;) {
print "List of integers: ";
my $input = <STDIN>;
chomp $input;
#integers = split /[\s,]+/, $input;
#
# Verify inputted "number" is numeric and an integer
#
for my $integer ( #integers ) {
if( not looks_like_number $integer ) {
warn qq(Invalid number entered: "$integer");
next INPUT;
}
if( $integer != int $integer ) {
warn qq(Invalid integer entered: "$integer");
next INPUT;
}
}
#
# Exit if there's at least one integer in #integers
#
last if #integers;
}
say "Integers: " . join ": ", #integers;
This is how I did it:
$input = 0;
while($input != -1)
{
print "add input, finish with -1", "\n";
$input = <STDIN>;
chomp($input);
push(#array, $input);
}
#You also need to remove the last input, -1, with pop:
pop(#array);
print #array;
Console output:
add input, finish with -1
1
add input, finish with -1
2
add input, finish with -1
-1
12
If the user inputs a tab delimited string of numbers directly,
you can use the splice function to separate the strings.
#array = splice(/\t/,$array[0])
Here's one approach, taking a comma-separated list of integers:
my $input = <STDIN>;
chomp($input);
if ($input !~ m/^(\d+(,\d+)*)?$/) { die('invalid input'); }
my #input = split(/,/, $input );
Or you could read one integer per line:
my #input;
while (my $input = <STDIN>) {
chomp($input);
if ($input !~ m/^\d+$/) { die('invalid input'); }
push(#input, $input );
} ## end while

How to truncate a string to a specific length in perl?

I am just unable to find "truncate a string to a specific length" in Perl.
Is there any built in way?
UPDATE:
input: $str = "abcd";
output (truncate for 3 characters): $str is abc
You want to use the substr() function.
$shortened = substr( $long, 0, 50 ); # 50 characters long, starting at the beginning.
For more, use perldoc
perldoc -f substr
In your case, it would be:
$str = 'abcd';
$short = substr( $str, 0, 3 );
For a string of arbitrary length, where truncate length can be longer than string length, I would opt for a substitution
$str =~ s/.{3}\K.*//s;
For shorter strings, the substitution will not match and the string will be unchanged. The convenient \K escape can be replaced with a lookbehind assertion, or a simple capture:
s/(?<=.{3}).*//s # lookbehind
s/(.{3}).*/$1/s # capture
It's probably useful to also mention that, instead of substr() or regular expressions, you could use printf or sprintf.
See perldoc -f sprintf :
For string conversions, specifying a precision truncates the string to
fit the specified width:
printf '<%.5s>', "truncated"; # prints "<trunc>"
printf '<%10.5s>', "truncated"; # prints "< trunc>"
As long as your original string is at least 3 characters long, you can use a call to substr as an lvalue.
my $str = "abcd";
substr($str, 3) = "";
print "$str\n"; # prints "abc"
The initial length of the string may need to be checked, as if it is shorter than 3 characters, the return value of this call to substr cannot be assigned to (see perldoc -f substr for more information) and attempting to do so will cause an error.
If I understand correctly, you need to do like php wordwrap() a string, so :
use Text::Format;
print Text::Format->new({columns => 50})->format($string);
If you just need the first N characters :
print substr $string, 0, 50;
Or you can use regexp to do the same.
#!/usr/bin/perl -w
use strict;
my $str = "abcd";
$str =~ /(\w{0,3})/;
print $1;
The most natural way is to use substr to extract the part you want:
$first_n = substr($string, 0, $n);
If you only want to modify the string and you are certain it is at least the desired length:
substr($string, $n) = '';
If you are not certain, you can do:
use List::Util "min";
substr($string, min($n, length($string))) = '';
or catch the exception:
eval { substr($string, $n) = '' };