Trouble padding a Perl string array without increasing array length - perl

I have an integer value my $reading = 1200;.
I have an array my #DigitField = "000000000";
I want to replace the right-hand 4 elements of the array with $reading's value, and I want to do this programmatically using Perl's length function as shown below.
I've tried.
my #DigitField = "000000000";
my $reading = 1200;
splice #DigitField, length(#DigitField) + 1, length $reading, $reading;
print #DigitField;
but I'm getting
0000000001200
and I want the string to remain nine characters wide.
What are some other ways to replace part of a Perl string array?

I think you are possibly confused - the # sigil indicates #DigitField is an array variable. A string is not an array.
I think you want to format the number:
my $reading = 1200;
my $digitfield = sprintf('%09d', $reading);
print $digitfield, "\n";
I added a \n to the end of the print, this adds a newline. Depending on the context of your program, you may or may not want this in the final.

Related

Convert the position of a character in a string to account for "gaps" (i.e., non alphanumeric characters in the string)

In a nutshell
I have a string that looks something like this ...
---MNTSDSEEDACNERTALVQSESPSLPSYTRQTDPQHGTTEPKRAGHT--------LARGGVAAPRERD
And I have a list of positions and corresponding characters that looks something like this...
position character
10 A
12 N
53 V
54 A
This position/character key doesn't account for hyphen (-) characters in the string. So for example, in the given string the first letter M is in position 1, the N in position 2, the T in position 3, etc. The T preceding the second chunk of hyphens is position 47, and the L after that hyphen chunk is position 48.
I need to convert the list of positions and corresponding characters so that the position accounts for hyphen characters. Something like this...
position character
13 A
15 N
64 V
65 A
I think there should be a simple enough way to do this, but I am fairly new so I am probably missing something obvious, sorry about that! I am doing this as part of bigger script, so if anyone had a way to accomplish this using perl that would be amazing. Thank you so much in advance and please let me know if I can clarify anything or provide more information!
What I tried
At first, I took a substring of characters equal to the position value, counted the number of hyphens in that substring, and added the hyphen count onto the original position. So for the first position/character in my list, take the first 10 characters, and then there are 3 hyphens in that substring, so 10+3 = 13 which gives the correct position. This works for most of my positions, but fails when the original position falls within a bunch of hyphens like for positions 53 and 54.
I also tried grabbing the character by taking out the hyphens and then using the original position value like this...
my #array = ($string =~ /\w/g);
my $character = $array[$position];
which worked great, but then I was having a hard time using this to convert the position to include the hyphens because there are too many matching characters to match the character I grabbed here back to the original string with hyphens and find the position in that (this may have been a dumb thing to try from the start).
The actual character seems not to be relevant. It's enough to count the non-hyphens:
use strict;
use warnings;
use Data::Dumper;
my $s = '---MNTSDSEEDACNERTALVQSESPSLPSYTRQTDPQHGTTEPKRAGHT--------LARGGVAAPRERD';
my #positions = (10,12,53,54);
my #transformed = ();
my $start = 0;
for my $loc(#positions){
my $dist = $loc - $start;
while ($dist){
$dist-- if($s =~ m/[^-]/g);
}
my $pos = pos($s);
push #transformed, $pos;
$start = $loc;
}
print Dumper \#transformed;
prints:
$VAR1 = [
13,
15,
64,
65
];

What is the fastest/easiest way to increase a number in a string variable in Powershell?

I have the following Powershell variable
$var = "AB-0045"
I would like to increase the number in the string to become "AB-0046".
I can do:
$newNumber = [int]$var.Substring($var.length -4,4) + 1
Which will give me the desired number 46, but then I have to append that 46 as a string to a new string "AB-00".
Is there a better way to do that?
Now that you have the integer, you'll have to convert back to string formatted in the way you'd like and concatenate.
I'd recommend adding to "AB-" rather than "AB-00" in case your number goes over 100.
To pad leading zeros, you can use the -f operator.
e.g. "{0:d4}" -f 45
You'll still need to get the integer first (45 in the example) from your original string.
I tested with regex class Replace() method and string class Split() method with string formatter. Split() seems faster provided your string is always in the same format. The Replace() method does not care what happens before the last 4 numbers:
# Replace Method
[regex]::Replace($var,'\d{4}$',{([int]$args[0].Value+1).ToString('0000')})
# Split method
$a,[int]$b = $var.split('-'); "{0}-{1:0000}" -f $a,++$b

Function to split string in matlab and return second number

I have a string and I need two characters to be returned.
I tried with strsplit but the delimiter must be a string and I don't have any delimiters in my string. Instead, I always want to get the second number in my string. The number is always 2 digits.
Example: 001a02.jpg I use the fileparts function to delete the extension of the image (jpg), so I get this string: 001a02
The expected return value is 02
Another example: 001A43a . Return values: 43
Another one: 002A12. Return values: 12
All the filenames are in a matrix 1002x1. Maybe I can use textscan but in the second example, it gives "43a" as a result.
(Just so this question doesn't remain unanswered, here's a possible approach: )
One way to go about this uses splitting with regular expressions (MATLAB's strsplit which you mentioned):
str = '001a02.jpg';
C = strsplit(str,'[a-zA-Z.]','DelimiterType','RegularExpression');
Results in:
C =
'001' '02' ''
In older versions of MATLAB, before strsplit was introduced, similar functionality was achieved using regexp(...,'split').
If you want to learn more about regular expressions (abbreviated as "regex" or "regexp"), there are many online resources (JGI..)
In your case, if you only need to take the 5th and 6th characters from the string you could use:
D = str(5:6);
... and if you want to convert those into numbers you could use:
E = str2double(str(5:6));
If your number is always at a certain position in the string, you can simply index this position.
In the examples you gave, the number is always the 5th and 6th characters in the string.
filename = '002A12';
num = str2num(filename(5:6));
Otherwise, if the formating is more complex, you may want to use a regular expression. There is a similar question matlab - extracting numbers from (odd) string. Modifying the code found there you can do the following
all_num = regexp(filename, '\d+', 'match'); %Find all numbers in the filename
num = str2num(all_num{2}) %Convert second number from str

why strcat() doesn't return a string in Matlab?

I'm trying to access multiple files in a for loop, like this:
age = xlsread(strcat('Pipeline_BO_2013_',names(2),'_CDBU.xlsx'), 'Data', 'H:I')
It returns an error the filename must be string. So I did following test:
filename = strcat('Pipeline_BO_2013_',names(2),'_CDBU.xlsx')
filename =
'Pipeline_BO_2013_0107_CDBU.xlsx'
isstr(filename)
ans =
0
This is so weird. Could any one help me out? Thank you so much.
It looks like names is a cellstr and not a char array. If so, indexing in to it with parentheses like names(2) will return a 1-long cellstr array, not a char array. And when strcat is called with any of its arguments as a cellstr, it returns a cellstr. Then xlsread errors because it wants a char, not a cellstr.
Instead of just calling isstr or ischar on filename, do class(filename) and it'll tell you what it is.
Another clue is that filename is displayed with quotes. This is how cellstrs are displayed. If it were a char array, it would be displayed without quotes.
If this is the case, and names is a cellstr, you need to use {} indexing to "pop out" the cell contents.
filename = strcat('Pipeline_BO_2013_',names{2},'_CDBU.xlsx')
Or you can use sprintf, which you may find more readable, and will be more flexible once you start interpolating multiple arguments of different types.
filename = sprintf('Pipeline_BO_2013_%s_CDBU.xlsx', names{2})
% An example of more flexibility:
year = 2013;
filename = sprintf('Pipeline_BO_%04d_%s_CDBU.xlsx', year, names{2})

Why does substr not return undef at the end of a string?

I'm not sure whether this is defined behaviour or not. I have the following code:
use strict;
use warnings;
use Data::Dumper;
my $string = 'aaaaaa0aaaa';
my $char = substr($string, length($string), 1);
my $char2 = substr($string, length($string)+1, 1);
print Dumper($char);
print Dumper($char2);
Besides getting one warning about substr() past the end of a string, I'm confused about the output:
$VAR1 = '';
$VAR1 = undef;
Perldoc says about substr:
substr EXPR,OFFSET,LENGTH
If OFFSET and LENGTH specify a substring that is partly outside the string, only the part within the string is returned. If the substring is beyond either end of the string, substr() returns the undefined value and produces a warning.
Both length($string) and length($string) + 1 are beyond the (zero-indexed) end of the string, so I don't know why substr returns the empty string in one case and undef in the other. Does it have to do with the NULL character that C uses for string termination and that is somehow returned by substr in the first case, so that there is an "invisible" last character to this string that is not counted by length? Am I missing something obvious here?
There are a couple of issues here. Firstly you should consider the substr offset to indicate position between characters thus:
S T R I N G
0 1 2 3 4 5 6
so you can see that offset 6 - the length of the string - is at the end of the string, not beyond it.
Secondly the length parameter of substr serves as an upper limit to the number of characters returned, not a requirement. That is what the documentation means by only the part within the string is returned.
Putting these together, a call like substr 'STRING', 6, 1 - asking for a maximum of one character at the end of the string - returns the empty string, while asking for anything beyond the end of the string (or before its start) gives undef.
substr($string, length($string), 1)
This gave you an empty string because, substr considers the offset between 0 to len(str), and anything beyond that range is undef.
So, substr("aa", 2, 1); -> will give you the empty string after last a
and,substr("aa", 3, 1); -> Will give you undef (Substring completely outside range)
Similarly: -
substr("aa", 2, 2); -> Will give you the empty string after last
a (Substring partly outside the range)
Now, for the second one: -
substr($string, length($string) + 1, 1)
This is already past the last allowed offset. So it returns undef value.
Suppose: -
$str = "abcd";
Then, the index will look like: -
a b c d undef
0 1 2 3 len(str) len(str) + 1
UPDATE: -
So, as #Borodin explained in his post, the character d comes between the offsets - 3 and len(str) in the above example.
But, if we try to access anything beyond len(str) including len(str), we will get an empty string, as in the documentation, which says that -
If OFFSET and LENGTH specify a substring that is partly outside the
string, only the part within the string is returned.
Also, if we try to access anything beyond len(str) excluding the len(str), we will get undef value, as in docs: -
If the substring is beyond either end of the string, substr() returns
the undefined value and produces a warning.