I can't understand the proposed solutions in other questions or resolve the php error Uninitialized string offset: 0 .
I used this code to create acronyme from a string
$article = 'the Central intelligence agency';
$words = array('the', 'of', 'to' );
$pattern = '/\b(?:' . join('|', $words) . ')\b/i';
$entityWords = preg_replace($pattern, '', $article);
$words = explode(" ", $entityWords);
var_dump($words);
$entityAcro = "";
foreach ($words as $letter) {
-> $entityAcro .= $letter[0];
}
echo strtoupper( $entityAcro );
I get this result :
Notice: Uninitialized string offset: 0 ....line (->)
Notice: Uninitialized string offset: 0 ....line (->)
CIA
I don't understand this solution : "you must know if it exist (isset)"
I manage multiple organizations and I can't know before how many word there are inside string.
Issue resolved with this solution:
foreach ($words as $letter) {
if(!empty($letter[0])){
$entityAcro .= $letter[0];
}
}
I had to verify the existence of each word $letter[0] in the array before showing the result of the foreach condition
I need to evaluate a series of strings that I want to convert into a hash of arrays. Take into account that, in this case, I want to add an array to an entry in a hash that it is already storing an array. I need to get the following hash:
ConfigurationHash{'Editor'} = (John, Mary, Jane, Peter)
I have stripped down my code to this example:
use strict;
use warnings;
my %ConfigurationHash;
my $String1 = "Editor=John,Mary";
my $String2 = "Editor=Jane,Peter";
my #Line1 = split ("=", $String1);
my #Line2 = split ("=", $String2);
my $Variable1 = #Line1[0];
my $Value1 = #Line1[1];
my $Variable2 = #Line2[0];
my $Value2 = #Line2[1];
my #Values1Array = split(",", $Value1);
my #Values2Array = split(",", $Value2);
if ( ! exists $ConfigurationHash{$Variable1} ) {
$ConfigurationHash{$Variable1} = #Values1Array;
}
else {
push (#ConfigurationHash{$Variable1}, #Values1Array);
}
which produces the following error:
Experimental push on scalar is now forbidden at ./test.pl line 25, near "#Values1Array)"
Execution of ./test.pl aborted due to compilation errors.
I know that the problem lies in references/dereferences, but my knowledge of perl is so basic that I'm not able to figure how to get there by myself.
Could anybody show me how to do it? I would also appreciate if you could show me how to iterate the values of the array in the hash once it is created.
It's unclear why you have $String2 and its derivatives in your code as they are never used. This code processes both strings
You simply need to push the list of values to the array corresponding to $Variable1 (dreadful choice of identifier) in the hash. Accomplish this by dereferencing the array element
use strict;
use warnings;
my %config;
my $s1 = 'Editor=John,Mary';
my $s2 = 'Editor=Jane,Peter';
for ( $s1, $s2 ) {
my ($key, #values) = split /[=,]/;
push #{ $config{$key} }, #values;
}
use Data::Dumper;
print Dumper \%config;
output
$VAR1 = {
'Editor' => [
'John',
'Mary',
'Jane',
'Peter'
]
};
This line isn't doing what you think it does.
$ConfigurationHash{$Variable1} = #Values1Array;
If you printed out what $ConfigurationHash{$Variable1} contains you'll find it only contains the size of #Values1Array.
You should be fine to use push but with a slight modification to what you've written.
push #{$ConfigurationHash{$Variable1}}, #Values1Array;
I've also removed the brackets as you don't need them.
As for iterating over the array, it is no different to iterating over a regular array. You were likely having problems iterating over it before as you didn't have an array
foreach my $whatever (#{$ConfigurationHash{$Variable1}})
{
# Code
}
Thank you to all who posted answers. #Borodin, you're right, I missed a second block that used $String2 and its derivatives, but I think it was obvious it was at the end and was similar to the if-else block in my original code.
Thank you, #chris-turner, for giving me the hint on how to use push the right way and pointing out the error in the $ConfigurationHash{$Variable1} = #Values1Array;
With all these contributions I figured out that the right code I was expecting is:
use strict;
use warnings;
my %ConfigurationHash;
my $String1 = "Editor=John,Mary";
my $String2 = "Editor=Jane,Peter";
my #Line1 = split ("=", $String1);
my #Line2 = split ("=", $String2);
my $Variable1 = $Line1[0];
my $Value1 = $Line1[1];
my $Variable2 = $Line2[0];
my $Value2 = $Line2[1];
my #Values1Array = split(",", $Value1);
my #Values2Array = split(",", $Value2);
if ( ! exists $ConfigurationHash{$Variable1} ) {
$ConfigurationHash{$Variable1} = \#Values1Array;
}
else {
#push (#ConfigurationHash{$Variable1}, #Values1Array);
push #{$ConfigurationHash{$Variable1}}, #Values1Array;
}
if ( ! exists $ConfigurationHash{$Variable2} ) {
$ConfigurationHash{$Variable2} = \#Values2Array;
}
else {
#push (#ConfigurationHash{$Variable2}, #Values2Array);
push #{$ConfigurationHash{$Variable2}}, #Values2Array;
}
use Data::Dumper;
print Dumper \%ConfigurationHash;
Which outputs the following:
$VAR1 = {
'Editor' => [
'John',
'Mary',
'Jane',
'Peter'
]
};
I need a code in VBScript or batch to replace 5 Caracters (the bold numbers below) in a line of a text file to change ports numbers.
change_port.vbs:
prefsFile = "%userprofile%\Desktop\teste.msrcincident"
prefsFile = CreateObject("WScript.Shell").ExpandEnvironmentStrings(prefsFile)
newPrefs = "5500"
Set fso = CreateObject("Scripting.FileSystemObject")
json = fso.OpenTextFile(prefsFile).ReadAll
Set re = New RegExp
re.Pattern = "":*?",*,"
json = re.Replace(json, ": & newPrefs & ",*,")
fso.OpenTextFile(prefsFile, 2).Write(json)
Original text file:
RCTICKET="65538,1,10.0.0.1:54593,*,ucIdnri2n4QPf/bv92mtx4w2qliCNdyDgBpHPr7nJFdxYL2/dR+iel9Mh4zgD6QR,*,*,Fbjf5rcIrdrlnibnisrzRcO8tsY=" PassStub="HG)7HbhIZPTiKy" RCTICKETENCRYPTED="1" DtStart="1457700115" DtLength="142560" L="0"/></UPLOADINFO>
Expected result text file:
RCTICKET="65538,1,10.0.0.1:5500,*,ucIdnri2n4QPf/bv92mtx4w2qliCNdyDgBpHPr7nJFdxYL2/dR+iel9Mh4zgD6QR,*,*,Fbjf5rcIrdrlnibnisrzRcO8tsY=" PassStub="HG)7HbhIZPTiKy" RCTICKETENCRYPTED="1" DtStart="1457700115" DtLength="142560" L="0"/></UPLOADINFO>
Can anyone help me?
Your search and replacement expressions are messed up. You're looking for a colon (:) followed by one or more digits (\d+ or [0-9]+) followed by a comma (,), and want to replace that with a colon followed by the new port number and a comma.
Change this:
re.Pattern = "":*?",*,"
json = re.Replace(json, ": & newPrefs & ",*,")
into this.
re.Pattern = ":\d+,"
json = re.Replace(json, ":" & newPrefs & ",")
Always keep your expressions as simple as possible.
I'm pretty close on this problem. What I have to do is filter out a cell array. The cell array can have a variety of items in it, but what I want to do is pull out the strings, using recursion. I am pretty close on this one. I just have an issue when the cells have spaces in them. This is what I should get:
Test Cases:
cA1 = {'This' {{{[1:5] true} {' '}} {'is '} false true} 'an example.'};
[filtered1] = stringFilter(cA1)
filtered1 => 'This is an example.'
cA2 = {{{{'I told '} 5:25 'her she'} {} [] [] ' knows'} '/take aim and reload'};
[filtered2] = stringFilter(cA2)
filtered2 => 'I told her she knows/take aim and reload'
Here is what I have:
%find the strings in the cArr and then concatenate them.
function [Str] = stringFilter(in)
Str = [];
for i = 1:length(in)
%The base case is a single cell
if length(in) == 1
Str = ischar(in{:,:});
%if the length>1 than go through each cell and find the strings.
else
str = stringFilter(in(1:end-1));
if ischar(in{i})
Str = [Str in{i}];
elseif iscell(in{i})
str1 = stringFilter(in{i}(1:end-1));
Str = [Str str1];
end
end
end
end
I tried to use 'ismember', but that didn't work. Any suggestions? My code outputs the following:
filtered1 => 'This an example.'
filtered2 => '/take aim and reload'
You can quite simplify your function to
function [Str] = stringFilter(in)
Str = [];
for i = 1:length(in)
if ischar(in{i})
Str = [Str in{i}];
elseif iscell(in{i})
str1 = stringFilter(in{i});
Str = [Str str1];
end
end
end
Just loop through all elements in the cell a test, whether it is a string or a cell. In the latter, call the function for this cell again. Output:
>> [filtered1] = stringFilter(cA1)
filtered1 =
This is an example.
>> [filtered2] = stringFilter(cA2)
filtered2 =
I told her she knows/take aim and reload
Here is a different implememntation
function str = stringFilter(in)
if ischar(in)
str = in;
elseif iscell(in) && ~isempty(in)
str = cell2mat(cellfun(#stringFilter, in(:)', 'uni', 0));
else
str = '';
end
end
If it's string, return it. If it is a cell apply the same function on all of the elements and concatenate them. Here I use in(:)' to make sure it is a row vector and then cell2mat concatenates resulting strings. And if the type is anything else return an empty string. We need to check if the cell array is empty or not because cell2mat({}) is of type double.
The line
Str = ischar(in{:,:});
is the problem. It doesn't make any sense to me.
You're close to the getting the answer, but made a few significant but small mistakes.
You need to check for these things:
1. Loop over the cells of the input.
2. For each cell, see if it itself is a cell, if so, call stringFilter on the cell's VALUE
3. if it is not a cell but is a character array, then use its VALUE as it is.
4. Otherwise if the cell VALUE contains a non character, the contribution of that cell to the output is '' (blank)
I think you made a mistake by not taking advantage of the difference between in(1) and in{1}.
Anyway, here's my version of the function. It works.
function [out] = stringFilter(in)
out = [];
for idx = 1:numel(in)
if iscell (in{idx})
% Contents of the cell is another cell array
tempOut = stringFilter(in{idx});
elseif ischar(in{idx})
% Contents are characters
tempOut = in{idx};
else
% Contents are not characters
tempOut = '';
end
% Concatenate the current output to the overall output
out = [out, tempOut];
end
end
I am trying to teach myself Perl and I have been struggling... Last night I did a program to calculate the average of a set of numbers that the user provided in order to learn about lists and user input so today I thought I would do a Morse Code decoder to learn about Hashes. I have looked through the book that I bought and it doesn't really explain hashes very well... it actually doesn't explain a lot of things very well. Any help would be appreciated!
Anyways, I am wanting to write a program that decodes the morse code that the user inputs. So the user would enter:
-.-.
.-
-
...
!
.-.
..-
.-..
.
The exclamation point would signify a separate word. This message would return "Cats Rule" to the user. Below is the code I have so far... Remember.. I have been programming in perl for under 24 hours haha.
Code:
use 5.010;
my %morsecode=(
'.-' =>'A', '-...' =>'B', '-.-.' =>'C', '-..' =>'D',
'.' =>'E', '..-.' =>'F', '--.' =>'G', '....' =>'H',
'..' =>'I', '.---' =>'J', '-.-' =>'K', '.-..' =>'L',
'--' =>'M', '-.' =>'N', '---' =>'O', '.--.' =>'P',
'--.-' =>'Q', '.-.' =>'R', '...' =>'S', '-' =>'T',
'..-' =>'U', '...-' =>'V', '.--' =>'W', '-..-' =>'X',
'-.--' =>'Y', '--..' =>'Z', '.----' =>'1', '..---' =>'2',
'...--' =>'3', '....-' =>'4', '.....' =>'5', '-....' =>'6',
'--...' =>'7', '---..' =>'8', '----.' =>'9', '-----' =>'0',
'.-.-.-'=>'.', '--..--'=>',', '---...'=>':', '..--..'=>'?',
'.----.'=>'\'', '-...-' =>'-', '-..-.' =>'/', '.-..-.'=>'\"'
);
my #k = keys %morsecode;
my #v = values %morsecode;
say "Enter a message in morse code separated by a line. Use the exclamation point (!) to separate words. Hit Control+D to signal the end of input.";
my #message = <STDIN>;
chomp #message;
my $decodedMessage = encode(#message);
sub encode {
foreach #_ {
if (#_ == #k) {
return #k;
#This is where I am confused... I am going to have to add the values to an array, but I don't really know how to go about it.
}
else if(#_ == '!') {return ' '}
else
{
return 'Input is not valid';
}
}
}
Your code contains two syntactic errors: foreach requires a list to iterate over; this means parens. Unlike C and other languages, Perl doesn't support else if (...). Instead, use elsif (...).
Then there are a few semantic mistakes: The current value of an iteration is stored in $_. The array #_ contains the arguments of the call to your function.
Perl comparse strings and numbers differently:
Strings Numbers
eq ==
lt <
gt >
le <=
ge >=
ne !=
cmp <=>
Use the correct operators for the task at hand, in this case, the stringy ones.
(Your code #_ == #k does something, namely using arrays in numeric context. This produces the number of elements, which is subsequenty compared. #_ == '!' is just weird.)
What you really want to do is to map the inputted values to a list of characters. Your hash defines this mapping, but we want to apply it. Perl has a map function, it works like
#out_list = map { ACTION } #in_list;
Inside the action block, the current value is available as $_.
We want our action to look up the appropriate value in the hash, or include an error message if there is no mapping for the input string:
my #letters = map { $morsecode{$_} // "<unknown code $_>" } #message;
This assumes ! is registered as a space in the morsecode hash.
We then make a single string of these letters by joining them with the empty string:
my $translated_message = join "", #letters;
And don't forget to print out the result!
The complete code:
#!/usr/bin/perl
use strict; use warnings; use 5.012;
my %morsecode=(
'.-' =>'A', '-...' =>'B', '-.-.' =>'C', '-..' =>'D',
'.' =>'E', '..-.' =>'F', '--.' =>'G', '....' =>'H',
'..' =>'I', '.---' =>'J', '-.-' =>'K', '.-..' =>'L',
'--' =>'M', '-.' =>'N', '---' =>'O', '.--.' =>'P',
'--.-' =>'Q', '.-.' =>'R', '...' =>'S', '-' =>'T',
'..-' =>'U', '...-' =>'V', '.--' =>'W', '-..-' =>'X',
'-.--' =>'Y', '--..' =>'Z', '.----' =>'1', '..---' =>'2',
'...--' =>'3', '....-' =>'4', '.....' =>'5', '-....' =>'6',
'--...' =>'7', '---..' =>'8', '----.' =>'9', '-----' =>'0',
'.-.-.-'=>'.', '--..--'=>',', '---...'=>':', '..--..'=>'?',
'.----.'=>'\'', '-...-' =>'-', '-..-.' =>'/', '.-..-.'=>'"',
'!' =>' ',
);
say "Please type in your morse message:";
my #codes = <>;
chomp #codes;
my $message = join "", map { $morsecode{$_} // "<unknown code $_>" } #codes;
say "You said:";
say $message;
This produces the desired output.
There's a lot of value in learning the how and why, but here's the what:
sub encode {
my $output;
foreach my $symbol (#_) {
my $letter = $morsecode{$symbol};
die "Don't know how to decode $symbol" unless defined $letter;
$output .= $letter
}
return $output;
}
or even as little as sub encode { join '', map $morsecode{$_}, #_ } if you're not too worried about error-checking. #k and #v aren't needed for anything.
Searching for values in hashes is a very intense job, you are better of by just using a reverse hash. You can easily reverse a hash with the reverse function in Perl. Also, while watching your code I have seen that you will be able to enter lower-case input. But while searching in hashes on keys, this is case-sensitive. So you will need to uppercase your input. Also, I do not really like the way to "end" an STDIN. An exit word/sign would be better and cleaner.
My take on your code
my %morsecode=(
'.-' =>'A', '-...' =>'B', '-.-.' =>'C', '-..' =>'D',
'.' =>'E', '..-.' =>'F', '--.' =>'G', '....' =>'H',
'..' =>'I', '.---' =>'J', '-.-' =>'K', '.-..' =>'L',
'--' =>'M', '-.' =>'N', '---' =>'O', '.--.' =>'P',
'--.-' =>'Q', '.-.' =>'R', '...' =>'S', '-' =>'T',
'..-' =>'U', '...-' =>'V', '.--' =>'W', '-..-' =>'X',
'-.--' =>'Y', '--..' =>'Z', '.----' =>'1', '..---' =>'2',
'...--' =>'3', '....-' =>'4', '.....' =>'5', '-....' =>'6',
'--...' =>'7', '---..' =>'8', '----.' =>'9', '-----' =>'0',
'.-.-.-'=>'.', '--..--'=>',', '---...'=>':', '..--..'=>'?',
'.----.'=>'\'', '-...-' =>'-', '-..-.' =>'/', '.-..-.'=>'\"'
);
my %reversemorse = reverse %morsecode;
print "Enter a message\n";
chomp (my $message = <STDIN>);
print &encode($message);
sub encode{
my $origmsg = shift(#_);
my #letters = split('',$origmsg);
my $morse = '';
foreach $l(#letters)
{
$morse .= $reversemorse{uc($l)}." ";
}
return $morse;
}