Home > Archive > PERL Miscellaneous > August 2004 > Joining 2 strings
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
|
| Hi! Thanks for looking at my problem. I have a problem with joining 2
strings together.
Here is the problem:
I read a file into perl line by line. Each line becomes a string
element in an array. I need to recognize the first, second and third
elements of the array and join them on a single line in the output;
then join the fourth,fifth and sixth elements on the second line. My
inital plan was to use the join() function, but I had problems. The
join function does not join 2 strings on the same line. Can someone
help?(Pardon me if this is supposed to be an easy problem. I am new to
Perl)
My current stage:
my $n;
$n= 1;
open (FILE, 'sample.out');
while (defined ($_ = <FILE> )){
if ($n < 4){
$array[$n] = $_;
print join(' ',$array[$n], $array[$n+1]);#does not
work
print join(' ',@array); #does not work too
$n = $n +1 ;
}
else {
print $_;
print "time for next line";
$n =1;
}
}
close FILE;
| |
|
| "Sim" <selena_kid@yahoo.com> wrote in message
news:82bbfd98.0408071246.297ca742@posting.google.com...
>
> My current stage:
>
> my $n;
> $n= 1;
> open (FILE, 'sample.out');
> while (defined ($_ = <FILE> )){
at this stage $_ contains the end of line character(s)
remove it with chomp;
chomp;
add the "\n" to every print after this
> if ($n < 4){
> $array[$n] = $_;
> print join(' ',$array[$n], $array[$n+1]);#does not
> work
this does not work because array[$n+1] is not defined at this stage
> print join(' ',@array); #does not work too
define 'does not work'. do you mean the newlines?
try again
gnari
| |
| Jürgen Exner 2004-08-07, 8:56 pm |
| Sim wrote:
> Hi! Thanks for looking at my problem. I have a problem with joining 2
> strings together.
>
> Here is the problem:
>
> I read a file into perl line by line. Each line becomes a string
> element in an array.
I am not sure if putting the strings into an array is part of your
requirements or part of an attempt to solve your underlying problem
> I need to recognize the first, second and third
> elements of the array and join them on a single line in the output;
> then join the fourth,fifth and sixth elements on the second line. My
> inital plan was to use the join() function, but I had problems. The
> join function does not join 2 strings on the same line. Can someone
> help?(Pardon me if this is supposed to be an easy problem. I am new to
> Perl)
Because in this part you don't talk about the array any more but instead you
are talking about strings and lines.
You need to be careful about what you are talking about. "Lines", "strings",
and "array elements" are quite different entities.
For example join() doesn't know and doesn't care about of lines. It takes
whatever the array contains and just concatenates it.
If those text pieces happen to be lines, then you will get a single string
containing multiple lines.
I'm assuming that you simply want to print every three lines as one single
line.
> open (FILE, 'sample.out');
> unless while (defined ($_ = <FILE> )){
> if ($n < 4){
> $array[$n] = $_;
> print join(' ',$array[$n], $array[$n+1]);#does not
> work
> print join(' ',@array); #does not work too
[rest of script snipped]
You are not removing the newline character anywhere. Therefore even after
you join the lines into a single string, they are still three lines, just
packed into a single string.
You should be able to do something similar to this (untested, just to give
you an idea):
open (FILE, 'sample.out');
unless (eof FILE){ #warning: not stable; will fail if number of lines in
file is not dividable by 3
print chomp(<FILE> ) . chomp(<FILE> ) . <FILE>;
}
close FILE;
Or
open (FILE, 'sample.out');
while (<FILE> ){
chomp; print;
print "\n" unless ($. % 3)
}
close FILE;
jue
| |
| Tad McClellan 2004-08-08, 3:56 am |
| Sim <selena_kid@yahoo.com> wrote:
> open (FILE, 'sample.out');
You should always, yes *always*, check the return value from open():
open (FILE, 'sample.out') or die "could not open 'sample.out' $!";
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| Mladen Gogala 2004-08-08, 3:56 am |
| On Sat, 07 Aug 2004 13:46:07 -0700, Sim wrote:
> Hi! Thanks for looking at my problem. I have a problem with joining 2
> strings together.
>
> Here is the problem:
>
> I read a file into perl line by line. Each line becomes a string
> element in an array. I need to recognize the first, second and third
> elements of the array and join them on a single line in the output;
> then join the fourth,fifth and sixth elements on the second line. My
> inital plan was to use the join() function, but I had problems. The
> join function does not join 2 strings on the same line. Can someone
> help?(Pardon me if this is supposed to be an easy problem. I am new to
> Perl)
open (FILE,"<",'sample.out') || die "Cannot open sample.out:$!\n";
my @file=<FILE>;
chomp(@file);
print join(' ',@file[0..2]),"\n";
print join(' ',@file[3..5]),"\n";
close(FILE);
This, I believe, does exactly what you wanted to do.
--
A city is a large community where people are lonesome together.
| |
| John W. Krahn 2004-08-08, 8:56 pm |
| Sim wrote:
> Hi! Thanks for looking at my problem. I have a problem with joining 2
> strings together.
>
> Here is the problem:
>
> I read a file into perl line by line. Each line becomes a string
> element in an array. I need to recognize the first, second and third
> elements of the array and join them on a single line in the output;
> then join the fourth,fifth and sixth elements on the second line. My
> inital plan was to use the join() function, but I had problems. The
> join function does not join 2 strings on the same line. Can someone
> help?(Pardon me if this is supposed to be an easy problem. I am new to
> Perl)
You don't really need an array, you can just use string concatenation.
open FILE, '<', 'sample.out' or die "Cannot open sample.out: $!";
my $line;
while ( <FILE> ) {
chomp;
if ( $. % 3 ) {
$line .= "$_ ";
}
else {
print "$line$_\n";
$line = '';
}
}
Of course, if you really want to use an array:
open FILE, '<', 'sample.out' or die "Cannot open sample.out: $!";
my @lines;
while ( <FILE> ) {
chomp;
if ( $. % 3 ) {
push @lines, $_;
}
else {
print join( ' ', splice( @lines ), $_ ), "\n";
}
}
John
--
use Perl;
program
fulfillment
| |
|
| Thanks for the reply. I tried the given solutions and they all work in
a way similar to this:
Raw data from input file:
abcdefghi
jklmno
pqr
Output:
pqrmnoghi
The third line overwrite the second which in turn overwrites the
first. What I am trying to accomplish instead is to put the 3 lines
on a single line without any overwriting to give this (on a single
line):
abcdefghijklmnopqr
Can this be done?
Reason why I choose arrays is that later on I have to recognize
individual numbers from the input data and filter them based on the
criterion of a minimum value. This is the overall picture.
For example, suppose my input file contains:
"First data is 1
Second data is 2
Third data is 3"
My script should be able to read the lines, filter and take away for
example, data that read a data with < 2, and display them on the same
line:
"Second data is 2 Third data is 3" #Note that the entire first line is
filtered
I read that in arrays, I can control each of the elements, so if
"First data is 1" is an array, I can recognize "1" as an element, and
set a criterion that is has to be >2 or else it will not be displayed.
This is my first idea. Please enlighten me if there are better ways to
do it.
| |
| Jim Gibson 2004-08-09, 3:57 pm |
| In article <82bbfd98.0408090807.694220b2@posting.google.com>, Sim
<selena_kid@yahoo.com> wrote:
> Thanks for the reply. I tried the given solutions and they all work in
> a way similar to this:
>
> Raw data from input file:
> abcdefghi
> jklmno
> pqr
>
> Output:
>
> pqrmnoghi
>
> The third line overwrite the second which in turn overwrites the
> first. What I am trying to accomplish instead is to put the 3 lines
> on a single line without any overwriting to give this (on a single
Neither Perl's join nor its concatenate operator (.) will overwrite the
scalars involved in the operation. What you probably have here is
embedded carriage returns in your concatenated or joined string that is
causing some letters to be overwritten when they are printed.
What platform are you using?
Please post a complete program demonstrating your problem, along with
the platform you are using and the perl version, so people may help you
better.
| |
|
| For clarification,
The aim of the program is to
1. Format the data such that 3 lines (containing the information about
a single record) are displayed as a single line with no overwriting.
2. Analyze the data such that a specific value in each record meets a
requirement (say above a specific value.)
Problems:
1. I cannot join/ append the 3 lines on a single line. Solutions
posted above overwrite the 3 lines, on top of one another. This is
described in my previous post (post #7).
2. As for the data analysis, I am considering using arrays to
represent each record. In this way, I can identify, via pattern
matching, the particular array elements that match a certain
requirement.
Please advise on:
Problem #1 in particular, and
Any tips for problem #2 if you have any (better solutions??)
Platform info:
ActivePerl 5.8.4 build 810
Text editor: Secure Shell Client for Workstations Version 3.2.9(build
283)
Window XP
| |
| Jim Gibson 2004-08-09, 8:56 pm |
| In article <82bbfd98.0408091537.42eeb87e@posting.google.com>, Sim
<selena_kid@yahoo.com> wrote:
> For clarification,
>
> The aim of the program is to
> 1. Format the data such that 3 lines (containing the information about
> a single record) are displayed as a single line with no overwriting.
> 2. Analyze the data such that a specific value in each record meets a
> requirement (say above a specific value.)
>
> Problems:
> 1. I cannot join/ append the 3 lines on a single line. Solutions
> posted above overwrite the 3 lines, on top of one another. This is
> described in my previous post (post #7).
I don't think that the lines are getting overwritten, but I can't say
for sure because you have not posted your version of the suggested
solutions. You may be getting different results than other posters
because your platform or perl version may be different, or you may have
made some mistake in coding those solutions. Please post a complete,
minimal program that you think is causing your input lines to be
overwritten.
>
> 2. As for the data analysis, I am considering using arrays to
> represent each record. In this way, I can identify, via pattern
> matching, the particular array elements that match a certain
> requirement.
An array is an excellent way of storing your data. If your records are
always three lines, you can store a record as an array element where
the element is a reference to another array (anonymous) that has 3
elements, each of which is one of the input lines for that record.
Something like:
my @array;
while(my $line1 = <DATA> ) {
my $line2 = <DATA>;
my $line3 = <DATA>;
chomp($line1,$line2,$line3);
push( @array, [$line1,$line2,$line3]);
}
You can then reference the lines in the nth record (n starting at zero)
with:
$array[n][0], $array[n][1], and $array[n][2]
for any n in ( 0 .. $#array ).
| |
| Jürgen Exner 2004-08-09, 8:56 pm |
| Sim wrote:
> Thanks for the reply. I tried the given solutions and they all work in
> a way similar to this:
>
> Raw data from input file:
> abcdefghi
> jklmno
> pqr
>
> Output:
>
> pqrmnoghi
>
> The third line overwrite the second which in turn overwrites the
> first. What I am trying to accomplish instead is to put the 3 lines
> on a single line without any overwriting to give this (on a single
> line):
>
> abcdefghijklmnopqr
A wild guess: the original file was created on a Windows system and you are
processing this file on a Unix system? On Windows a logical newline consists
of a carriage return character and linefeed character while on Unix the
logical newline is only the linefeed character.
Therefore when you chomp() the line on Unix then only the LF will be
removed, leaving the CR behind.
And that in turn causes the cursor to move back to the beginning of the line
after printing each partial string, giving the appearance as if the lines
were over each other.
> Can this be done?
Sure, just remove the CR, too, not only the LF.
If this is not the problem, them please post a minimal, but complete program
that demonstrates your problem.
I doubt that anyone can help you without a concrete code sample.
jue
| |
| Tad McClellan 2004-08-10, 3:56 am |
| Sim <selena_kid@yahoo.com> wrote:
> The aim of the program is to
> 1. Format the data such that 3 lines (containing the information about
> a single record) are displayed as a single line with no overwriting.
> 1. I cannot join/ append the 3 lines on a single line.
I can:
------------------------------------------
#!/usr/bin/perl
use warnings;
use strict;
my $line1 = "first line\n";
my $line2 = "second line\n";
my $line3 = "third line\n";
chomp $line1;
chomp $line2;
my $single_line = "$line1$line2$line3";
print $single_line;
------------------------------------------
> Please advise on:
> Problem #1 in particular, and
Show us a short and complete program that we can run, including
the data, and we will help you fix it.
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| bowsayge 2004-08-10, 3:57 pm |
| Sim said to us:
[...]
> Problems:
> 1. I cannot join/ append the 3 lines on a single line.
[...]
This works for bowsayge:
while (scalar @lines) {
print join " ", splice @lines, 0, 3;
print "\n";
}
--
my (@str) = split //,'ttneuhb .aenpesrrJ oei wl';
my (@ndx, @arr) = qw(8 3 18 19 1 9 21 17 24 5 10 6 13
23 2 11 15 0 12 7 14 22 4 20 16);
$arr[$ndx[$_]] = $str[$_] for (@ndx); print @arr, "\n";
| |
| Brian Kell 2004-08-10, 3:57 pm |
| On 9 Aug 2004 16:37:45 -0700, Sim <selena_kid@yahoo.com> wrote:
> Problems:
> 1. I cannot join/ append the 3 lines on a single line. Solutions
> posted above overwrite the 3 lines, on top of one another. This is
> described in my previous post (post #7).
>
> ...
>
> Window XP
What might be happening is this: A newline on Windows is \r\n, or CRLF, or
"carriage return, line feed". If you take off the line feed from the end
of each line, you still have the carriage return left over, which moves
the cursor back to the beginning of the current line. So, if you take
three lines and join them, you get something like this, where "\r" means a
carriage return:
"abcdefghi\rjklmno\rpqr"
Now, if you print that string to the screen, Windows prints "abcdefghi",
backs up to the first column, prints "jklmno", backs up to the first
column again, and prints "pqr", so what you see on the screen is
"pqrmnoghi". The string itself contains all the letters, and if you write
the string to a file it will contain all the letters, but because of the
embedded carriage returns if you print the string to the screen it appears
to have been overwritten.
If you use the length function to get the number of characters in your
"pqrmnoghi" string, you should find that it contains 20 characters instead
of the 9 you were probably expecting.
So try doing something like
$string =~ s/\r//g;
after you join it. Or before you join it.
Brian
| |
| Anno Siegel 2004-08-10, 9:00 pm |
| bowsayge <bowsayge@nomail.afraid.org> wrote in comp.lang.perl.misc:
> Sim said to us:
>
> [...]
> [...]
>
> This works for bowsayge:
>
> while (scalar @lines) {
No need for "scalar" there. The conditional of "while" is already in
scalar context (boolean, specifically).
> print join " ", splice @lines, 0, 3;
> print "\n";
> }
You could print the lines and the line feed in a single statement. Then
"while" can become a statement modifier, and the whole thing a one-liner:
print join( " ", splice @lines, 0, 3), "\n" while @lines;
Anno
| |
|
| I managed to solve the problem! It is very similar to the solution Jue
posted. Here's how it goes. I wish to thank everyone who has thought
through this problem. My MSN is jjsimz@hotmail.com. I am a college
Physics student, and if you have any physics question, I might be of a
little help. =)
#!/usr/bin/perl
use strict;
open (FILE, 'sample.out') or die "could not open 'sample.out'!!! ";
open (OUTPUTFILE, '>>output.out') or die "could not open
'output.out'!!! ";
while (<FILE> ) {
s/^\s*((.*\S)?)\s*$/$1/; #removes spaces before and after the
string
print (OUTPUTFILE $_, ' ');
if ($. % 3 == 0) {print (OUTPUTFILE "\n")}
}
close FILE;
close OUTPUTFILE;
| |
| Eric Bohlman 2004-08-11, 3:59 am |
| selena_kid@yahoo.com (Sim) wrote in
news:82bbfd98.0408101451.69866dfa@posting.google.com:
> I managed to solve the problem! It is very similar to the solution Jue
> posted. Here's how it goes. I wish to thank everyone who has thought
> through this problem. My MSN is jjsimz@hotmail.com. I am a college
> Physics student, and if you have any physics question, I might be of a
> little help. =)
>
>
> #!/usr/bin/perl
> use strict;
You want 'use warnings;' here as well.
>
> open (FILE, 'sample.out') or die "could not open 'sample.out'!!! ";
> open (OUTPUTFILE, '>>output.out') or die "could not open
> 'output.out'!!! ";
Error messages for files should say *why* the file couldn't be opened;
stick a $! in both messages.
> while (<FILE> ) {
> s/^\s*((.*\S)?)\s*$/$1/; #removes spaces before and after the
> string
The FAQ recommends doing this in two substitutions (neither of which
requires capturing) rather than one; it's usually faster.
> print (OUTPUTFILE $_, ' ');
> if ($. % 3 == 0) {print (OUTPUTFILE "\n")}
> }
> close FILE;
> close OUTPUTFILE;
| |
| Joe Smith 2004-08-28, 8:56 pm |
| Sim wrote:
> s/^\s*((.*\S)?)\s*$/$1/; #removes spaces before and after the string
That takes longer to execute than doing it in two steps.
s/^\s+//;
s/\s+$//;
See
perldoc -q "blank space"
for more info.
-Joe
|
|
|
|
|