How do I place a colon into a string two characters from the end using Perl? - perl

I'm trying to find a way to place a colon ( : ) into a string, two characters from the end of the string.
Examples of $meetdays:
1200 => 12:00900 => 9:001340 =>13:40
Not sure if this should be a regular expression or just another function that I'm not aware of.

Can also use substr() as well.....
my $string = "1200";
substr $string, -2, 0, ':';
# $string => '12:00';

s/(?=..$)/:/
Don't use roe's suggestion of $&. perldoc perlvar:
The use of this variable anywhere in a program imposes a considerable performance penalty on all regular expression matches. See "BUGS".

You could try this:
s/..$/:$&/
it matches two-characters at the end of the string, and replaces it with a colon, and the matched string (i.e. the two characters).
EDIT
Fixed sed-backref to the perl equivalent.

roe's answer "works" , but its rather inobvious regex.
I would more go for
s/(^.*)(..$)/$1:$2/
Because I just love backrefs.
Its overkill for what you're doing, but to me its more semantically expressive.

The Perl equivalent of sed's & is $&, so it should be:
$s = s /..$/:$&/s;

Related

Perl s/$array[1]\b/$array[1] won't replace

I would like to replace the string $array[1] by the actual variable value.
the \b doesn't seem to work
Does anyone know how the replace the array variable ? What's the delimiter ?
s/$array[1]\b/$array[1]
The [ ... ] has a special meaning in regular expressions (it defines a "character class"). If you want to use [ to mean a [, then you need to escape it with a \.
s/\$array\[1]/$array[1]/
Update: Added escape to $. Removed \b.
I would recommend a real templating engine to perform such a substitution, this will allow you to extend it to things that don't look exactly like $array[1] without making it more complicated, but you will need to alter your input to what the templating engine expects. One option is Text::Template.
use strict;
use warnings;
use Text::Template 'fill_in_string';
my $input = 'foo {$array[1]} bar';
my #array = 1..10;
my $rendered = fill_in_string $input, HASH => {array => \#array};
print $rendered, "\n"; # foo 2 bar

index argument contains . perl

If a string contains . representing any character, index doesn't match on it. What to do so that it takes . as any character?
For ex,
index($str, $substr)
if $substr contains . anywhere, index will always return -1
thanks
carol
That is not possible. The documentation says:
The index function searches for one string within another, but without
the wildcard-like behavior of a full regular-expression pattern match.
...
The keywords, you can use for further googlings are:
perl regular expression wildcard
Update:
If you just want to know, if your string matches, using a regular expression could look like that:
my $string = "Hello World!";
if( $string =~ /ll. Worl/ )
{
print "Ahoi! Position: ".($-[0])."\n";
}
This is matching a single character.
$-[0] is the offset into the string of the beginning of the entire
match.
-- http://perldoc.perl.org/perlvar.html
If you want to have a pattern, that is matching an arbitary amount of arbitary characters, you could choose a pattern like...
...
if( $string =~ /ll.*orl/ )
{
...
See perlvar for further information about special perl variables. You will find the variable #LAST_MATCH_START and some explanation about $-[0] over there. There are several more variables, that can help you to find sub matches and to gather other interessting information about your matches...
From perldoc -f index, you can see index() doesn't have any regex syntax:
index STR,SUBSTR
The index function searches for one string within another, but without the wildcard-like behavior of a full regular-
expression pattern match. It returns the position of the first occurrence of SUBSTR in STR at or after POSITION. If
POSITION is omitted, starts searching from the beginning of the string. POSITION before the beginning of the string or after
its end is treated as if it were the beginning or the end, respectively. POSITION and the return value are based at 0 (or
whatever you've set the $[ variable to--but don't do that). If the substring is not found, "index" returns one less than the
base, ordinarily "-1"
A simple test:
$ perl -e 'print index("1234567asdfghj.","j.")'
13
Use regex:
$str =~ /$substr/g;
$index = pos();

Modify the last two characters of a string in Perl

I am looking for a solution to a problem:
I have the NSAP address which is 20 characters long:
39250F800000000000000100011921680030081D
I now have to replace the last two characters of this string with F0 and the final string should look like:
39250F80000000000000010001192168003008F0
My current implementation chops the last two characters and appends F0 to it:
my $nsap = "39250F800000000000000100011921680030081D";
chop($nsap);
chop($nsap);
$nsap = $nsap."F0";
Is there a better way to accomplish this?
You can use substr:
substr ($nsap, -2) = "F0";
or
substr ($nsap, -2, 2, "F0");
Or you can use a simple regex:
$nsap =~ s/..$/F0/;
This is from substr's manpage:
substr EXPR,OFFSET,LENGTH,REPLACEMENT
substr EXPR,OFFSET,LENGTH
substr EXPR,OFFSET
Extracts a substring out of EXPR and returns it.
First character is at offset 0, or whatever you've
set $[ to (but don't do that). If OFFSET is nega-
tive (or more precisely, less than $[), starts
that far from the end of the string. If LENGTH is
omitted, returns everything to the end of the
string. If LENGTH is negative, leaves that many
characters off the end of the string.
Now, the interesting part is that the result of substr can be used as an lvalue, and be assigned:
You can use the substr() function as an lvalue, in
which case EXPR must itself be an lvalue. If you
assign something shorter than LENGTH, the string
will shrink, and if you assign something longer
than LENGTH, the string will grow to accommodate
it. To keep the string the same length you may
need to pad or chop your value using "sprintf".
or you can use the replacement field:
An alternative to using substr() as an lvalue is
to specify the replacement string as the 4th argu-
ment. This allows you to replace parts of the
EXPR and return what was there before in one oper-
ation, just as you can with splice().
$nsap =~ s/..$/F0/;
replaces the last two characters of a string with F0.
Use the substr( ) function:
substr( $nsap, -2, 2, "F0" );
chop( ) and the related chomp( ) are really intended for removing line ending characters - newlines and so on.
I believe that substr( ) will be quicker than using a regular expression.

How can I manually interpolate string escapes in a Perl string?

In perl suppose I have a string like 'hello\tworld\n', and what I want is:
'hello world
'
That is, "hello", then a literal tab character, then "world", then a literal newline. Or equivalently, "hello\tworld\n" (note the double quotes).
In other words, is there a function for taking a string with escape sequences and returning an equivalent string with all the escape sequences interpolated? I don't want to interpolate variables or anything else, just escape sequences like \x, where x is a letter.
Sounds like a problem that someone else would have solved already. I've never used the module, but it looks useful:
use String::Escape qw(unbackslash);
my $s = unbackslash('hello\tworld\n');
You can do it with 'eval':
my $string = 'hello\tworld\n';
my $decoded_string = eval "\"$string\"";
Note that there are security issues tied to that approach if you don't have 100% control of the input string.
Edit: If you want to ONLY interpolate \x substitutions (and not the general case of 'anything Perl would interpolate in a quoted string') you could do this:
my $string = 'hello\tworld\n';
$string =~ s#([^\\A-Za-z_0-9])#\\$1#gs;
my $decoded_string = eval "\"$string\"";
That does almost the same thing as quotemeta - but exempts '\' characters from being escaped.
Edit2: This still isn't 100% safe because if the last character is a '\' - it will 'leak' past the end of the string though...
Personally, if I wanted to be 100% safe I would make a hash with the subs I specifically wanted and use a regex substitution instead of an eval:
my %sub_strings = (
'\n' => "\n",
'\t' => "\t",
'\r' => "\r",
);
$string =~ s/(\\n|\\t|\\n)/$sub_strings{$1}/gs;

How do I get the length of a string in Perl?

What is the Perl equivalent of strlen()?
length($string)
perldoc -f length
length EXPR
length Returns the length in characters of the value of EXPR. If EXPR is
omitted, returns length of $_. Note that this cannot be used on an
entire array or hash to find out how many elements these have. For
that, use "scalar #array" and "scalar keys %hash" respectively.
Note the characters: if the EXPR is in Unicode, you will get the num-
ber of characters, not the number of bytes. To get the length in
bytes, use "do { use bytes; length(EXPR) }", see bytes.
Although 'length()' is the correct answer that should be used in any sane code, Abigail's length horror should be mentioned, if only for the sake of Perl lore.
Basically, the trick consists of using the return value of the catch-all transliteration operator:
print "foo" =~ y===c; # prints 3
y///c replaces all characters with themselves (thanks to the complement option 'c'), and returns the number of character replaced (so, effectively, the length of the string).
length($string)
The length() function:
$string ='String Name';
$size=length($string);
You shouldn't use this, since length($string) is simpler and more readable, but I came across some of these while looking through code and was confused, so in case anyone else does, these also get the length of a string:
my $length = map $_, $str =~ /(.)/gs;
my $length = () = $str =~ /(.)/gs;
my $length = split '', $str;
The first two work by using the global flag to match each character in the string, then using the returned list of matches in a scalar context to get the number of characters. The third works similarly by splitting on each character instead of regex-matching and using the resulting list in scalar context