Convert array to a string with newlines embeded in string - arrays

i need to convert a perl array to a single string variable, containing all array items separated with newlines.
my $content = "";
#names=('A','C','C','D','E');
$content = $content . join($", #names) . "\n";
print $content;
I intend the output to be like:
A
C
C
D
E
But i get:
A C C D E
Why isn't the newline \n character being honoured?

Since it appears that you want a newline not just between each line, but after the last one too, you can use any of the following:
join("\n", #names) . "\n"
join("", map "$_\n", #names)
join("\n", #names, "")
These are equivalent except when the array in empty. In that situation, the first results in a newline, and the other result in an empty string.
By the way,
$content = $content . EXPR;
can be written as
$content .= EXPR;

To join an array with newlines in between, use
join("\n", #array)
Your code uses the contents of the $" variable as the separator, which by default contains a space.

Do this instead:
$content = $content . join("\n", #names);

The $" variable holds the value that Perl uses between array elements when it interpolates an array in a double-quoted string. By default (and you haven't changed it), it's a space.
Perhaps you were thinking about the input or output record separators, $/ or $\.
But, you don't really want to play with those variables. If you want a newline, use a newline:
join "\n", #array;

Related

split string to some parts and replace a one sub-string with another string

I am trying to replace a string with a substring which is located in between other two parts.
To describe, I have a file which contains some text in. In this text file there is one word which some parts of it are written in different character, as an example like:
acc\E34rate
acc\?4rate
acc§54rate
.....
What I want to write as a code is, to lookup for for acc and then rate and then replace what is between them with u. Because all strings are in commen with the the first part and the last part.
I wonder how I can do it in Perl?
Thanks!
Update: including Code
well what I have written is:
use strict;
use warnings;
my #stringArray = ('acc\E34rate', 'acc\?4rate');
my $find = '\E34';
my $replace = 'u';
my #newArray;
foreach my $str(#stringArray)
{
my $pos = index($str, $find);
while($pos > -1) {
substr($str, $pos, length($find), $replace);
$pos = index($str, $find, $pos + length($replace));
}
push #newSrray, $str;
}
foreach(#newArray)
{
print "$_\r\n";
}
To simplify, I have added an array instead of a file. Because it works for only a proper word rather than the whole array/file.
I think this is what you want but the requirements are not clear. See perldoc perlre for more details.
#!/usr/bin/env perl
use strict;
use warnings;
my $begin = 'acc';
my $end = 'rate';
my $replace = 'u';
while( my $line = <DATA> ){
$line =~ s{ \Q$begin\E \S*? \Q$end\E }{$begin$replace$end}gmsx;
print $line;
}
__DATA__
acc\E34rate
acc\?4rate
acc§54rate
acc\E34rate acc\?4rate acc§54rate
accFOOacc
rateFOOrate
rateFOOrate accFOOacc
accFOOacc rateFOOrate
Try this:
$Text = "acc\E34rate
acc\?4rate
acc§54rate"; # This is the joined string (using enter key) after reading from the file
$Text =~ s/^acc.*?rate$/accutext/mg;
print $Text;
I've just tested it in my system and it is working fine.
Output:
accutext
accutext
accutext
m is to denote that the string is a multi line string and that each \n will be treated as an end of string character.
g is to replace all possible occurrences.
To get back as an array, split using \n.
Please note that the above code is written based on the assumption that each line in the file will begin and end with acc and text respectively and that there are no additional text after or before them in that line (ie, File is not having individual lines like "Driving acc\?4rate at 60kmph" and only "acc\?4rate").
In case this word is in between words in a sentence, replace below in the above code.
$Text =~ s/acc.*?rate/accutext/g;
Incidentally, this will work in all possible inputs too, including the code at the top.

How to type selected elements of an array in double quotes

Here, I'm trying to print the 2nd, 3rd and 4th elements of an array in double quotes and I've only been able to do it in single quotes.
my #fruits = ("apples", "oranges", "guavas", "passionfruits", "grapes");
my $a = 1;
while ($a<4){
print " '$fruits[$a]' \n";
$a += 1;
}
But I can't do this in single quotes. When I change the single quotes to double quotes and vice versa, it prints "$fruits[$a]"\n three times instead.
And when I change all quotes to double quotes, it gives an error which I understand why.
Please I really need help here.
And if I could get a way to print all three elements in double quotes without having to use a loop. Thanks!
To use " in a string delimited by ", escape it.
"foo: \"$bar\"\n"
You could also switch the delimiter (keeping in mind that "..." is short for qq"...").
qq{foo: "$bar"\n}
Always use
use strict;
use warnings;
even in the shortest Perl scripts.
In case of typos in the code, Perl will usually issue errors if you include them. Without, Perl will happily do weird, wrong and pointless things silently.
Your example will not print the entire array. Instead you will get:
'oranges'
'guavas'
'passionfruits'
The first index of an array is 0 and therefore 'apples' is skipped because $a is initialized with 1. The loop is also exited due to reaching the value 4 before printing out 'grapes'.
In order to print the entire array you would do:
if you need to use the index value $i somewhere:
for my $i (0 .. $#fruits) {
print " $i: '$fruits[$i]' \n";
}
($#fruits is the last index if #fruits, equal to the the size of the array minus 1. Since this array has 5 items, the index values range from 0 to 4)
otherwise:
foreach my $current_fruit (#fruits) {
print " '$current_fruit' \n";
}
where $current_fruit is set to each item in the array #fruits in its turn.
Quotes in Perl function as operators, and depending on which ones you use, they may or may not do various things with the included string.
In your examples, the double quotes will do interpolation on the string, substituting the value of $fruits[$a] and replacing the escape sequence \n. Therefore:
print " '$fruits[$a]' \n";
(for $a == 1) becomes:
'oranges'
Single quotes, in contrast, will not do interpolation.
Only single quotes themselves (and backslashes preceding single quotes) need to be escaped with a backslash. (Other backslashes can optionally be escaped.) All other character sequences will appear as they are, so the argument to print in:
print ' "$fruits[$a]" \n';
is considered entirely a literal string and thus
"$fruits[$a]" \n "$fruits[$a]" \n "$fruits[$a]" \n
is printed out.
To get the desired output, there are multiple ways to go about it:
The simplest way - but not easiest to read for complex strings - is to use double quotes and escape the included quotes:
print " \"$fruits[$a]\" \n";
You can use an generic notation for "...", which is qq{...} where {} are either a pair of braces (any of (), [], {} or <>) or the same other non-whitespace, non-word character, e.g.:
print qq{ "$fruits[$a]" \n};
or
print qq! "$fruits[$a]" \n!;
You can concatenate the string out of parts that you quote separately:
print ' "' . $fruits[$a] . '"' . " \n";
Which is easiest to read in code will depend on the complexity of the string and the variables contained: For really long strings with complex dereferences, indeces and hash keys you might want to use option 3, whereas for short ones 2 would be the best.
My entire edited code:
use strict;
use warnings;
my #fruits = ("apples", "oranges", "guavas", "passionfruits", "grapes");
for my $i (0 .. $#fruits) {
print " $i: \"$fruits[$i]\" \n";
print qq< $i: "$fruits[$i]" \n>;
print ' ' . $i . ': "' . $fruits[$i] . '"' . " \n";
}
foreach my $current_fruit (#fruits) {
print " \"$current_fruit\" \n";
print qq¤ "$current_fruit" \n¤;
print ' "' . $current_fruit . '"' . " \n";
}
You can learn more about the different quotes in Perl from the perldoc (or man on UNIX-like systems) page perlop and its section titled "Quote and Quote-like Operators".

how perl array works $"

I am confused about the outcome of this code.
my #lines;
for (my $count = 0; $count < 3; $count++) {
print "Give me input again ";
chomp (my $line = <STDIN>);
$lines[$count] = $line;
}
$" = "|";
print "#lines\n";
When I run the code, how does this: $" = "|"; work?
The results are One|Two|Three. How does the code work so that it puts "|" between each input?
It's simply what interpolation of arrays into double-quoted strings does.
"$foo\n"
is identical to
$foo . "\n"
and
"#lines\n"
is identical to
join($", #lines) . "\n"
This is documented in perldata and in perlvar.
$" is just a special variable name in perl that tells the interpreter how to separate array elements in double-quoted string context. The default value is a space, but the above code tells perl to use | instead. Hence One|Two|Three instead of the default of One Two Three if you left out that line.
See http://perldoc.perl.org/perlvar.html#General-Variables for more detail.

Perl print shows leading spaces for every element

I load a file into an array (every line in array element).
I process the array elements and save to a new file.
I want to print out the new file:
print ("Array: #myArray");
But - it shows them with leading spaces in every line.
Is there a simple way to print out the array without the leading spaces?
Yes -- use join:
my $delimiter = ''; # empty string
my $string = join($delimiter, #myArray);
print "Array: $string";
Matt Fenwick is correct. When your array is in double quotes, Perl will put the value of $" (which defaults to a space; see the perlvar manpage) between the elements. You can just put it outside the quotes:
print ('Array: ', #myArray);
If you want the elements separated by for example a comma, change the output field separator:
use English '-no_match_vars';
$OUTPUT_FIELD_SEPARATOR = ','; # or "\n" etc.
print ('Array: ', #myArray);

How to print 'AND' between array elements?

If I have an array with name like below.
How do I print "Hi joe and jack and john"?
The algorithm should also work, when there is only one name in the array.
#!/usr/bin/perl
use warnings;
use strict;
my #a = qw /joe jack john/;
my $mesg = "Hi ";
foreach my $name (#a) {
if ($#a == 0) {
$mesg .= $name;
} else {
$mesg .= " and " . $name;
}
}
print $mesg;
Usually we use an array join method to accomplish this. Here pseudo code:
#array = qw[name1 name2 name2];
print "Hey ", join(" and ", #array), ".";
Untested:
{ local $, = " and "; print "Hi "; print #a; }
Just use the special variable $".
$"="and"; #" (this last double quote is to help the syntax coloring)
$mesg="Hi #a";
To collect the perldoc perlvar answers, you may do one of (at least) two things.
1) Set $" (list separator):
When an array or an array slice is interpolated into a double-quoted
string or a similar context such as /.../ , its elements are separated
by this value. Default is a space. For example, this:
print "The array is: #array\n";
is equivalent to this:
print "The array is: " . join($", #array) . "\n";
=> $" affects the behavior of the interpolation of the array into a string
2) Set $, (output field separator):
The output field separator for the print operator. If defined, this
value is printed between each of print's arguments. Default is undef.
Mnemonic: what is printed when there is a "," in your print statement.
=> $, affects the behavior of the print statement.
Either will work, and either may be used with local to set the value of the special variable only within an enclosing scope. I guess the difference is that with $" you are not limited to the print command:
my #z = qw/ a b c /;
local $" = " and ";
my $line = "#z";
print $line;
here the "magic" happens on the 3rd line not at the print command.
In truth though, using join is the most readable, and unless you use a small enclosing block, a future reader might not notice the setting of a magic variable (say nearer the top) and never see that the behavior is not what is expected vs normal performance. I would save these tricks for small one-offs and one-liners and use the readable join for production code.

Resources